Я давно читал про них, ещё когда учился основам юникс, но как-то не было нужды с ними работать. И, вот, нужда возникла.
Некая программа (допустим, foo) не умеет писать вывод в stdout, только в файл. Даже "-" в качестве имени файла всего лишь создаёт файл с названием "-" [большинство умных программ под unix знают, что одиночный минус вместо имени файла означает вывод в stdout]. Аналогично она отвергает и /dev/stdout.
Другая же программа, обрабатывающая результаты первой, допустим, bar, читает из stdin и пишет в stdout. (если быть точным, первое — это трейсер специального вида, дающий двоичный дамп, а второе — конвертор, печатающий их же в человекочитаемом виде).
Нужно их объединить в конвеер.
Некрасивый вариант — использование обычного файла. Записал, прочитал.
Есть куда более красивый вариант — это именованные пайпы. Так как у пайпа есть имя, мы можем передать его как файл первой программе, а потом передать содержимое другой.
Выглядит это так:
Пайп в файловой системе выглядит так:
(акцент на букву 'p' первым символом).
Как это работает? Фактически, fifo aka named pipe — это «обыкновенный pipe», примерно такой, который кодируется палкой "|". Однако, у него есть ИМЯ и это имя можно указывать всюду, где требуется файл.
Программа, которая пишет в именованный пайп, ведёт себя с ним как с файлом. Т.е. пишет себе и пишет. Программа, которая читает — аналогично. Читает себе и читает. Чтение идёт в том порядке, как была осуществлена запись (FIFO — first in first out). Положения относительно пайпа (слева/справа) определяются тем, кто читает, а кто пишет.
Важная же особенность пайпа — способность тормознуть читающую/пищущую программу, если буфер пуст/переполнен.
Рассмотрим на примере чтения. Программа пишет в пайп одну строчку в секунду. Программа чтения читает с максимально возможной скоростью. Программа «вычитывает» всё, что было в буфере, и посылает следующий запрос. Ядро этот запрос задерживает до того момента, пока не появятся данные. Таким образом, можно не париться с синхронизацией — появятся данные, программа-обработчик получит управление обратно из read() и обработает очередную порцию данных.
Некая программа (допустим, foo) не умеет писать вывод в stdout, только в файл. Даже "-" в качестве имени файла всего лишь создаёт файл с названием "-" [большинство умных программ под unix знают, что одиночный минус вместо имени файла означает вывод в stdout]. Аналогично она отвергает и /dev/stdout.
Другая же программа, обрабатывающая результаты первой, допустим, bar, читает из stdin и пишет в stdout. (если быть точным, первое — это трейсер специального вида, дающий двоичный дамп, а второе — конвертор, печатающий их же в человекочитаемом виде).
Нужно их объединить в конвеер.
Некрасивый вариант — использование обычного файла. Записал, прочитал.
Есть куда более красивый вариант — это именованные пайпы. Так как у пайпа есть имя, мы можем передать его как файл первой программе, а потом передать содержимое другой.
Выглядит это так:
mkfifo mypipe cat mypipe | bar & foo mypipe& rm mypipe
Пайп в файловой системе выглядит так:
ls -l mypipe prw-r--r-- 1 root root 0 May 24 12:23 mypipe
(акцент на букву 'p' первым символом).
Как это работает? Фактически, fifo aka named pipe — это «обыкновенный pipe», примерно такой, который кодируется палкой "|". Однако, у него есть ИМЯ и это имя можно указывать всюду, где требуется файл.
Программа, которая пишет в именованный пайп, ведёт себя с ним как с файлом. Т.е. пишет себе и пишет. Программа, которая читает — аналогично. Читает себе и читает. Чтение идёт в том порядке, как была осуществлена запись (FIFO — first in first out). Положения относительно пайпа (слева/справа) определяются тем, кто читает, а кто пишет.
Важная же особенность пайпа — способность тормознуть читающую/пищущую программу, если буфер пуст/переполнен.
Рассмотрим на примере чтения. Программа пишет в пайп одну строчку в секунду. Программа чтения читает с максимально возможной скоростью. Программа «вычитывает» всё, что было в буфере, и посылает следующий запрос. Ядро этот запрос задерживает до того момента, пока не появятся данные. Таким образом, можно не париться с синхронизацией — появятся данные, программа-обработчик получит управление обратно из read() и обработает очередную порцию данных.