Книга: Linux программирование в примерах

9.4.2. Создание нелинейных конвейеров: /dev/fd/XX

9.4.2. Создание нелинейных конвейеров: /dev/fd/XX

Многие современные системы Unix, включая GNU/Linux, поддерживают в каталоге /dev/fd[98] специальные файлы. Эти файлы представляют дескрипторы открытых файлов с именами /dev/fd/0, /dev/fd/1 и т.д. Передача такого имени функции open() возвращает новый дескриптор файла, что в сущности является тем же самым, что и вызов dup() для данного номера дескриптора.

Эти специальные файлы находят свое применение на уровне оболочки: Bash, ksh88 (некоторые версии) и ksh93 предоставляют возможность замещения процесса (process substitution), что позволяет создавать нелинейные конвейеры. На уровне оболочки для входного конвейера используется запись '<(...)', а для выходного конвейера запись '>(...)'. Например, предположим, вам нужно применить команду diff к выводу двух команд. Обычно вам пришлось бы использовать временные файлы:

command1 > /tmp/out.$$.1
command2 > /tmp/out.$$.2
diff /tmp/out.$$.1 /tmp/out.$$.2
rm /tmp/out.$$.1 /tmp/out.$$.2

С замещением процессов это выглядит следующим образом:

diff <(command1) <(command2)

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

$ diff <(pwd) <(/bin/pwd)
1c1
< /home/arnold/work/prenhall/progex
---
> /d/home/arnold/work/prenhall/progex

Незамысловатая команда pwd является встроенной в оболочку: она выводит текущий логический путь, который управляется оболочкой с помощью команды cd. Программа /bin/pwd осуществляет обход физической файловой системы для вывода имени пути.

Как выглядит замещение процессов? Оболочка создает вспомогательные команды[99] ('pwd' и '/bin/pwd'). Выход каждой из них подсоединяется к каналу, причем читаемый конец открыт в дескрипторе нового файла для главного процесса ('diff'). Затем оболочка передает главному процессу имена файлов в/dev/fd в качестве аргументов командной строки. Мы можем увидеть это, включив в оболочке трассировку исполнения.

$ set -х /* Включить трассировку исполнения */
$ diff <(pwd) <(/bin/pwd) /* Запустить команду */
+ diff /dev/fd/63 /dev/fd/62 /* Трассировка оболочки: главная,
 программа, обратите внимание на аргументы */
++ pwd /* Трассировка оболочки: вспомогательные программы */
++ /bin/pwd
1c1 /* Вывод diff */
< /home/arnold/work/prenhall/progex
---
> /d/home/arnold/work/prenhall/progex

Это показано на рис. 9.6.


Рис. 9.6. Замещение процесса

Если на вашей системе есть /dev/fd, вы также можете использовать преимущества этой возможности. Однако, будьте осторожны и задокументируйте то, что вы делаете. Манипуляции с дескриптором файла на уровне С значительно менее прозрачны, чем соответствующие записи оболочки!

Оглавление книги


Генерация: 1.503. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз