Именованные каналы
FIFO (First In, First Out) – способ организации и манипулирования данными относительно времени и приоритетов. Этот способ описывает принцип технической обработки очереди или обслуживания конфликтных требований путём упорядочения процесса по принципу "первым пришёл первым обслужен" (ПППО).
FIFO, также известный как именованный канал, представляет собой специальный файл, похожий на канал, но с именем в ФС. Несколько процессов могут обращаться к этому специальному файлу для чтения и записи, как к любому обычному файлу.
Таким образом, имя работает только как ориентир для процессов, которым необходимо использовать имя в ФС.
FIFO обладает теми же характеристиками, что и любой другой файл. Например, у него есть права, разрешения и метаданные.
Важной особенностью FIFO является то, что он обеспечивает двунаправленную связь.
В ОС можем создать FIFO с помощью команд mknod (используя букву "p" для обозначения типа FIFO) и mkfifo:
$ mkfifo pipe1
$ mknod pipe2 p
$ ls -l
prw-r--r-- 1 cuau 0 Oct 7 21:17 pipe1
prw-r--r-- 1 cuau 0 Oct 7 21:17 pipe2
Здесь можно видеть, что тип файла FIFO обозначен буквой "p".
Этот механизм позволяет создавать более сложные приложения, используя оболочку.
Именованные и анонимные каналы можно использовать вместе. В качестве примера можно создать обратную оболочку, объединяющую как FIFO, так и каналы.
Удобно использовать утилиту nc для создания клиент-серверного приложения, в котором "серверная” сторона предоставит свою оболочку, а “клиентская” сторона сможет получить к ней доступ.
Сначала необходимо установить пакет nc:
$ sudo dnf -y nc
Далее нужно создать FIFO с именем fifo_reverse, набрав:
mkfifo fifo_reverse
Затем следует войти в Систему с двумя разными пользователями, каждый из которых будет действовать как “клиент“ (например, "пользователь1”) и как “сервер” (например, “пользователь2”). Для запуска этого конвейера в оболочке user2 выполняется:
user2_prompt$ bash -i < fifo_reverse |& nc -l 127.0.0.1 1234 > fifo_reverse
В этом однострочной команде оболочка считывает содержимое FIFO и передает его интерактивной оболочке Bash.
Затем оба стандартных вывода и stderr интерактивной оболочки будут переданы команде nc, которая будет прослушивать порт 1234 с адресом 127.0.0.1.
И, наконец, когда “клиент” успешно установит соединение, nc запишет полученное в FIFO, и интерактивная оболочка сможет выполнить полученное.
Теперь, используя оболочку user1, выполняется:
user1_prompt$ nc 127.0.0.1 1234
user2_prompt$
В результате получено приглашение user2, но используя оболочку user1, объединяющую анонимные и именованные каналы.
Временные именованные каналы
В некоторых оболочках есть функция подстановки процессов, которая соединяет ввод или вывод списка команд с FIFO. Затем команды будут использовать имя этого FIFO-файла.
Обозначение для этого механизма в Bash и Zsh <(список команд) – для передачи результата списка в стандартный ввод фактической команды или >(список команд) – для передачи стандартного вывода фактической команды в стандартный ввод списка.
Для передачи выходных данных нескольких команд в команду wc:
$ wc -l \
<(find / -mindepth 1 -maxdepth 1 -type d) \
<(find /opt -mindepth 1 -maxdepth 1 -type d)
20 /proc/self/fd/11
2 /proc/self/fd/12
22 total
В этом примере вывода используется команда find, чтобы получить количество каталогов внутри каталогов / и /opt.
Условия использования каналов
Использование анонимного канала вместо именованного зависит от характеристик, которые нужно найти. Некоторые из них могут быть постоянством, двусторонней связью, наличием имени файла, созданием фильтра и ограничением прав доступа среди других.
Например, если требуется отфильтровать выходные данные команды несколько раз, использование анонимного канала кажется наиболее подходящим вариантом. Следует также помнить, что используемая оболочка будет играть центральную роль при работе с анонимными каналами.
С другой стороны, если требуется имя файла и нет необходимости хранить данные на диске, то ищется FIFO, если нужно только имя в качестве ссылки с содержимым, которое поступает непосредственно из другого процесса.