Как это работает
Программа применяет функцию mkfifoдля создания специального файла. Несмотря на то, что запрашиваете режим 0777, он заменяется пользовательской маской ( umask), устанавливаемой (в данном случае 022) точно так же, как при создании обычного файла, поэтому у результирующего файла режим 755. Если ваша umaskустановлена иначе, например, ее значение 0002, вы увидите другие права доступа у созданного файла.
Удалить FIFO можно как традиционный файл с помощью команды rmили внутри программы посредством системного вызова unlink.
У именованных каналов есть одно очень полезное свойство: поскольку они появляются в файловой системе, их можно применять в командах на месте обычного имени файла. Прежде чем вы продолжите программирование с использованием созданного вами файла FIFO, давайте исследуем поведение такого файла с помощью обычных команд для работы с файлом (упражнение 13.10).
Упражнение 13.10. Организации доступа к файлу FIFO
1. Сначала попробуйте прочесть (пустой) файл FIFO:
$ cat < /tmp/my_fifo
2. Теперь попытайтесь записать в FIFO. Вам придется использовать другой терминал, поскольку первая команда в данный момент "зависла" в ожидании появления каких-нибудь данных в FIFO:
$ echo "Hello World" > /tmp/my_fifo
Вы увидите вывод команды cat. Если не посылать никаких данных в канал FIFO, команда catбудет ждать до тех пор, пока вы не прервете ее выполнение, традиционно комбинацией клавиш +.
3. Можно выполнить обе команды одновременно, переведя первую в фоновый режим:
$ cat < /tmp/my_fifo &
[1] 1316
$ echo "Hello World" > /tmp/my_fifo
Hello World
[1]+ Done cat
$
Как это работает
Поскольку в канале FIFO не было данных, обе команды, catи echo, приостанавливают выполнение, ожидая, соответственно, поступления каких-нибудь данных и какого-либо процесса для их чтения.
На третьем шаге процесс catс самого начала заблокирован в фоновом режиме. Когда echoделает доступными некоторые данные, команда catчитает их и выводит в стандартный вывод. Обратите внимание на то, что она затем завершается, не дожидаясь дополнительных данных. Программа catне блокируется, т.к. канал уже закрылся, когда завершилась вторая команда, поместившая данные в FIFO, поэтому вызовы readв программе catвернут 0 байтов, обозначая этим конец файла.
Теперь, когда вы посмотрели, как ведут себя каналы FIFO при обращении к ним с помощью программ командной строки, давайте рассмотрим более подробно программный интерфейс, предоставляющий больше возможностей управления операциями чтения и записи при организации доступа к FIFO.
Примечание
В отличие от канала, созданного вызовом pipe, FIFO существует как именованный файл, но не как открытый файловый дескриптор, и должен быть открыт перед тем, как можно будет из него читать данные или в него записывать их. Открывается и закрывается канал FIFO с помощью функций openи close, которые вы ранее применяли к файлам, но с дополнительными функциональными возможностями. Вызову openпередается полное имя FIFO вместо полного имени обычного файла.
Открытие FIFO с помощью open
Основное ограничение при открытии канала FIFO состоит в том, что программа не может открыть FIFO для чтения и записи с режимом O_RDWR. Если программа нарушит это ограничение, результат будет непредсказуемым. Это очень разумное ограничение, т.к., обычно канал FIFO применяется для передачи данных в одном направлении, поэтому нет нужды в режиме O_RDWR. Процесс стал бы считывать обратно свой вывод, если бы канал был открыт для чтения/записи.
Если вы действительно хотите передавать данные между программами в обоих направлениях, гораздо лучше использовать пару FIFO или неименованных каналов, по одному для каждого направления передачи, или (что нетипично) явно изменить направление потока данных, закрыв и снова открыв канал FIFO. Мы вернемся к двунаправленному обмену данными с помощью каналов FIFO чуть позже в этой главе.
Другое различие между открытием канала FIFO и обычного файла заключается в использовании флага open_flag(второй параметр функции open) со значением O_NONBLOCK. Применение этого режима openизменяет способ обработки не только вызова open, но и запросов readи writeдля возвращаемого файлового дескриптора.
Читать дальше