LINUX.ORG.RU

Ipc: pipe и fd

 , ,


0

2

Приветствую. Может кто нибудь подсказать направление в котором искать Проблема в следующем Пишу программу получающую данные через пайп, как cat. Только ничего не выходит. Сначала создаю именованный канал, вызовом mkfifo с правами 0666. Он создаёт, но права не те, поэтому вызываю chmod с этими правами.

Но это все равно не помогает. Данные через пайп не поступают.

Вызываю cat test_data|myprg.

В интернете нашёл описание, что моя программа и cat потомки терминала и можно переназначить неименованные каналы, только делать это надо в потомке. Тоже ничего не вышло. Потомок создаётся, но данные не читает.

Сейчас изучаю исходники cat на предмет алгоритма, но там, что-то системное, хотелось бы попроще.

Спасибо.

cat test_data|myprg

А зачем тут mkfifo? Ну и это, ты бы код показал.

P.S. если ты полез читать исходники гнутого cat, то лучше не надо. Держи нормальный: https://github.com/openbsd/src/blob/master/bin/cat/cat.c

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Можно не показывать весь код? Опять все настроение испортят.

Гнутый cat выбрал потому, что не хотел разбираться с компиляцие, а сразу printf’ами посмотреть, что и как работает.

bsd cat скомпилился так:

gcc -o cat cat.c -lbsd

Кому интересно.

и в нем используется read(rfd…)

read - системная функции (не точно), их я использовать не хотел, потому, что мешать системные функции и высокоуровневые обертки для них «плохой тон».

я так пробовал:

#define STDIN 0

int main(int argc,char **argv)
{
    int sym;
    int count = 1;
    while((sym=getc(STDIN))!=EOF)
    {
	printf("%d %c\n", count++, sym);
    }
    return 0;
}

получил ошибку сегментации, поэтому пошел дальше пробовать прочитать символы из STDIN_FILENO функцией getc.

Sergeyka
() автор топика
Последнее исправление: Sergeyka (всего исправлений: 4)

Пишу программу получающую данные через пайп, как cat

ЯННП при чём тут mkfifo, но в любом случае, канал, или не канал – для cat это не имеет значения и ни чем не отличается от чтения из файла. Канал (хоть именованный, хоть нет) это и есть файл.

no-such-file ★★★★★
()

Особеность fifo в том что прочитал одно сообщение, насиловать дальше смысла нет ничего не придёт, закрывай файл и открывай по новой чтобы прочитать следущее, можно юзать сокеты, но fifo на чтении мелких сообщений лидируют, а сокеты на передаче большого количества данных за раз становятся оправданы.

s-warus ★★★
()
Ответ на: комментарий от no-such-file

Да, я уже посмотрел исходники studio.h Просто везде пишут дискриптор, когда это указатель, а в другом случае константа. Вот и заентересовался как из константы получается указатель и зачем это вобще понадобилось. Код исправил работает. Значит надо исходники stdlib смотреть?

Sergeyka
() автор топика
Последнее исправление: Sergeyka (всего исправлений: 2)
Ответ на: комментарий от s-warus

Ну я как бы в тегах указал ipc, хотя мне shared memory больше нравиться. Как в amiga OS. Было бы круто сп@#&ть это в Linux.

Sergeyka
() автор топика
Последнее исправление: Sergeyka (всего исправлений: 2)
Ответ на: комментарий от Sergeyka

я храмотный наверно тебя запутал.
В твоём случае вызов cat test_data|myprg сработает один раз после echo «хи-хи-ха-ха»>test_data нужно в цикле снова вызывать cat test_data|myprg.
Или в проге написать открыть файл test_data, прочитать, закрыть и снова открыть файл test_data ....

s-warus ★★★
()
Ответ на: комментарий от Sergeyka

#define STDIN 0

А почему 0? А что это за макрос?

getc

А ты случайно с char *gets(char *buf); или getchar() не путаешь?

С другой стороны зачем так сложно, вот у тебя

int argc

Номера строк.

char **argv

А это массив того что ты cat’ом туда загоняешь.

Ygor ★★★★★
()
Ответ на: комментарий от s-warus

Ну или я тебя. test_Data уже содержит данные (строку «привет мир», но не важно). Тест нужен для того, что бы прочитать это строку побайтно (кодировка ansi) , передав её через пайп. Это будет означать, что алгоритм верный. Читаю и передаю cat’ом. Цыкл в пироге есть, да, когда, читаю байты. С открытием файла и чтением проблем нет, но хотел читать через пайп. Всё получилось.

Sergeyka
() автор топика
Последнее исправление: Sergeyka (всего исправлений: 1)
Ответ на: комментарий от Ygor

STDIN, это я так stdin определил, потому, что нельзя быть уверенным, что stdin_fileno не переопределят.

Gets же строку читает, не не путаю.

Насчёт argv, а если бинарные данные передавать? Там же будет. 00 argc её посчитает?

Sergeyka
() автор топика
Ответ на: комментарий от Sergeyka

Просто везде пишут дискриптор, когда это указатель

Дескриптор это не указатель. Это внутренняя структура в ядре, описывающая файл. Которая идентифицируется со стороны пользовательского процесса числом. А FILE это вообще никакого отношения к ядру не имеющая структура уже в libc. Внезапно, но libc может работать и не в юникс системах, где работа с файлами может быть организованно как-то по другому. Но т.к. libc предоставляет абстракцию в виде FILE то это делает код переносимым

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Сбило с толку, что fgetc(file* высокоуровневая обёртка над read(fd,…), это значит, что file содержит какую-то инфу о fd и конвертация file -> fd должна быть в libc, надо смотреть fileno. План такой.

Sergeyka
() автор топика
Последнее исправление: Sergeyka (всего исправлений: 1)
Ответ на: комментарий от Sergeyka

это значит, что file содержит какую-то инфу о fd

Оно содержит этот самый fd в том числе, а ещё буфер. Когда ты делаешь fgetc оно читает не 1 символ, а сразу целый буфер, а потом отдаёт по одному в следующих вызовах fgetc и т.п. Но вникать во всё это не надо, и тем более как-то это использовать. libc даёт тебе заранее настроенный указатель STDIN. Всё, больше никуда лезть не нужно.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Вот нашел: libio/iolibio.h

#define _IO_fileno(FP) ((FP)->_fileno

Это значит, что File содержит дискриптор в _fileno. Похоже, что мне хотелось странного получить File из fd, но такой функции нет. Из File можно fd получить, а обратно - нет, стандартными способами во всяком случае.

Sergeyka
() автор топика
Ответ на: комментарий от no-such-file

Но Вы же в этом разбираетесь, Вам зачем это понадобилось?

Да и в лекции

https://yztm.ru/epo/epo_z6l5/ Профессор говорит, что «Каналы не могут использоваться в качестве средства межпроцессного взаимодействия между независимыми процессами.» Но если форкнуть дочерний процесс, все можно. А оказывается можно и так читать. Это какой-то другой канал? Или выкинуть нафиг эту лекцию. Так и появился код выше, идея была такой: форкаю процесс, sh конвертит fd в file* и fgetc(fd) сработает нормально. Хотел на него всю работу свалить.

Sergeyka
() автор топика
Последнее исправление: Sergeyka (всего исправлений: 3)
Ответ на: комментарий от Sergeyka

Я не понял, что ты хочешь и зачем, ну вот например можно так:

#include <stdio.h>


int main(int argc, char **argv)
{
    char sym;
    int count = 1;
    while ((sym = getchar()) != EOF)
    {
        printf("%d %c\n", count++, sym);
    }
    return 0;
}

Ygor ★★★★★
()
Последнее исправление: Ygor (всего исправлений: 1)
Ответ на: комментарий от Sergeyka

Вам зачем это понадобилось

Для понимания как это работает. Если ты хочешь просто потыкать палкой, тогда конечно вперёд. Я имел в виду, что не нужно это использовать в прикладном коде.

Но если форкнуть дочерний процесс, все можно

Не можно. Дочерний процесс, это не независимый процесс. Он наследует дескрипторы родителя и разумеется через них он может с родителем общаться. И речь тут идёт про неименованные каналы. Именованные каналы на то и именованные, что их по имени может открыть любой процесс.

Так и появился код выше, идея была такой: форкаю процесс, sh конвертит fd в file*

У тебя какая-то каша в голове до сих пор. Ещё раз, не надо мешать в кучу fd и FILE*. Это разные интерфейсы работы с файлами. Внутренне они связаны, но лезть туда не надо. Используй что-то одно. При чём тут шелл вообще непонятно. Шелл тебе инициализирует стандартный ввод-вывод, libc для работы с FILE* сама тебе даёт FILE* STDIN/STDOUT для этого ввода-вывода. Т.е. тебе для этого не надо делать вообще ничего.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Для понимания как это работает. Если ты хочешь просто потыкать палкой, тогда конечно вперёд.

Я следую Федеральной программе импорта замещения одобренной правительством РФ :)

Я имел в виду, что не нужно это использовать в прикладном коде.

Просто меня учили автоматизировать как можно больше. Это значит, что хочу, что бы моя программа не падала с ошибкой.

Не можно. Дочерний процесс, это не независимый процесс. Он наследует дескрипторы родителя и разумеется через них он может с родителем общаться. И речь тут идёт про неименованные каналы.

Так, если внимательно читать лекцию, то станет ясно, что два независимых процесса на самом деле потомки терминала, это значит, что и общаться они могут через анонимные каналы.

У тебя какая-то каша в голове до сих пор.

Я меня план все разложить по полочкам.

Ещё раз, не надо мешать в кучу fd и FILE*. Это разные интерфейсы работы с файлами.

У меня программа на c.

Внутренне они связаны, но лезть туда не надо.

Что за буфер создаёт libc при инициализации структуры file?

Используй что-то одно.

А можно хотя бы библиотеки прилинковывать?

При чём тут шелл вообще непонятно.

См. выше.

Шелл тебе инициализирует стандартный ввод-вывод, libc для работы с FILE* сама тебе даёт FILE* STDIN/STDOUT для этого ввода-вывода. Т.е. тебе для этого не надо делать вообще ничего.

Есть промт для нейросети про эту инициализацию?

П.с. Как квотирование делать?

Sergeyka
() автор топика
Последнее исправление: Sergeyka (всего исправлений: 2)
Ответ на: комментарий от Sergeyka

Это ошибка компилятора gcc явного преобразования типа из int в File* нет, но программа компилируется, это значит мне полагается вознаграждение. Кто там gcc занимается? Столман-пидарас?

Sergeyka
() автор топика
Последнее исправление: Sergeyka (всего исправлений: 4)