Какой конец канала предназначен для ввода, а какой для вывода?
Недавно я начал подозревать, что я неправильно использую концы труб:
Из справочных страниц:
pipe () создает канал.. ..pipefd[0] ссылается на конец чтения канала. pipefd[1] относится к концу записи канала.
Так что, на мой взгляд, это было так:
.---------------------------.
/ /\
| pipedfd[0] pipedfd[1]| |
process1 ---> | | -----> process2
| input output| |
\____________________________\/
Однако код, который у меня здесь и работает, предполагает иное:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int pipedfd[2];
char buf[30];
pipe(pipedfd);
printf("writing to file descriptor #%d\n", pipedfd[1]);
write(pipedfd[1], "test", 5);
printf("reading from file descriptor #%d\n", pipedfd[0]);
read(pipedfd[0], buf, 5);
printf("read \"%s\"\n", buf);
return 0;
}
А именно он записывает на выход (?) Канала и считывает с входа (?) Канала?
2 ответа
В двух словах, поменяйте местами цифры 0
а также 1
в вашей диаграмме, и вы получили то, что я опишу ниже.
Со справочной страницы Mac OS X:
Функция pipe() создает канал (объект, который обеспечивает однонаправленный поток данных) и выделяет пару файловых дескрипторов. Первый дескриптор подключается к концу чтения канала; второй соединяется с концом записи.
Данные, записанные в файл [1], появляются (например, могут быть прочитаны) на файл [0]. Это позволяет отправлять выходные данные одной программы другой программе: стандартный исходный код источника устанавливается как конец записи канала; стандартный вход приемника настроен на чтение конца канала. Сам канал сохраняется до тех пор, пока все связанные с ним дескрипторы не будут закрыты.
Я опишу, как это часто используется, это может прояснить это. Представьте, что у вас есть процесс и вы хотите создать ребенка, которому вы хотите отправлять команды.
- Сначала вы звоните
pipe
и получите два файловых дескриптора. - Тогда вы звоните
fork
создать ребенка.- У ребенка закрываешь дескриптор файла записи (
fd[1]
) и оставьте чтение открытым. - В родительском вы делаете наоборот: вы закрываете чтение (
fd[0]
) файловый дескриптор и оставьте запись открытой.
- У ребенка закрываешь дескриптор файла записи (
- Теперь родитель может написать в "свою" часть трубы (
fd[1]
а ребенок может читать по другому (fd[0]
).
Закрытие не обязательно, но обычно делается. Если вам нужна двусторонняя связь, вам нужен второй набор файловых дескрипторов плюс второй вызов pipe
или вы используете двусторонний канал, такой как доменные сокеты Unix или именованный канал.
Справочная страница по Linux дляpipe
устраняет неоднозначность этого следующим образом:
Данные, записанные в конец записи канала, буферизуются ядром до тех пор, пока они не будут прочитаны из конца чтения канала.
Это ты read
от fd[0]
а также write
в fd[1]