Как стать автором
Обновить

named pipes в Unix

Время на прочтение2 мин
Количество просмотров34K
Я давно читал про них, ещё когда учился основам юникс, но как-то не было нужды с ними работать. И, вот, нужда возникла.

Некая программа (допустим, 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() и обработает очередную порцию данных.
Теги:
Хабы:
+56
Комментарии39

Публикации

Изменить настройки темы

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн