Страница 130 из 253
Открытие FIFO с установленным или сброшенным O_NONBLOCK демонстрирует следующее поведение:
open("/fifо/file", O_RDONLY, mode)
Блокируется до открытия FIFO для записи.
open("/fifo/file", O_RDONLY | O_NONBLOCK, mode)
Открывает файл, возвращаясь немедленно.
open("/fifo/file", O_WRONLY, mode)
Блокирует до открытия FIFO для чтения.
open("/fifo/file", O_WRONLY | O_NONBLOCK, mode)
Если FIFO был открыт для чтения, открывает FIFO и немедленно возвращается. В противном случае возвращает ошибку (возвращаемое значение -1 и errno установлен в ENXIO).
Как описано для обычных каналов, вызов read() для FIFO, который больше не открыт для чтения, возвращает конец файла (возвращаемое значение 0). Флаг O_NONBLOCK в данном случае неуместен. Для пустого канала или FIFO (все еще открытых для записи, но не содержащих данных) все становится интереснее:
read(fd, buf, count) и сброшенный O_NONBLOCK
Функция read() блокируется до тех пор, пока в канал или FIFO не поступят данные.
read(fd, buf, count) и установленный O_NONBLOCK
Функция read() немедленно возвращает -1 с установленным в errno EAGAIN.
В заключение, поведение write() более сложно. Для обсуждения этого нам нужно сначала представить концепцию атомарной записи. Атомарная запись — это такая запись, при которой все данные записываются целиком, не чередуясь с данными от других записей. POSIX определяет в <unistd.h> константу PIPE_BUF. Запись в канал или FIFO данных размером менее или равным PIPE_BUF байтов либо успешно завершается, либо блокируется в соответствии с подробностями, которые мы скоро приведем. Минимальным значением для PIPE_BUF является _POSIX_PIPE_BUF, что равняется 512. Само значение PIPE_BUF может быть больше; современные системы GLIBC определяют ее размер в 4096, но в любом случае следует использовать эту именованную константу и не ожидать, что PIPE_BUF будет иметь то же значение на разных системах.
Во всех случаях для каналов и FIFO write() добавляет данные в конец канала. Это происходит от того факта, что у каналов нет файловых смещений: в них нельзя осуществлять поиск.
Также во всех случаях, как упоминалось, записи размером вплоть до PIPE_BUF являются атомарными: данные не перемежаются с данными от других записей. Данные записи размером более PIPE_BUF байтов могут перемежаться с данными других записей в произвольных границах. Это последнее означает, что вы не можете ожидать, что каждая порция размером PIPE_BUF большого набора данных будет записана атомарно. Установка O_NONBLOCK не влияет на это правило.
Как и в случае с read(), когда O_NONBLOCK не установлен, write() блокируется до тех пор, пока все данные не будут записаны.
Наиболее все усложняется, когда установлен O_NONBLOCK. Канал или FIFO ведут себя следующим образом: