Как описано для обычных каналов, вызов 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 определяет в константу 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 ведут себя следующим образом:

размер ≥ nbytesразмер < abytes
nbytes ≤ PIPE_BUFwrite() успешнаwrite() возвращает (-1)/EAGAIN
размер > 0размер = 0
nbytes > PIPE_BUFwrite() записывает, что можетwrite() возвращает (-1)/EAGAIN

Для файлов, не являющихся каналами и FIFO и к которым может быть применен O_NONBLOCK, поведение следующее:

размер > 0 write() записывает, что может

размер = 0 write() возвращает -1/EAGAIN

Хотя есть ряд сбивающих с толку изменений поведения в зависимости от того, канал это или не канал, установлен O_NONBLOCK или сброшен, есть в канале место для записи или нет, а также в зависимости от размера предполагаемой записи, эти правила предназначены для упрощения программирования:

• Всегда можно отличить конец файла: read() возвращает 0 байтов.

• Если нет доступных для чтения данных, read() либо завершается успешно, либо возвращает указание «нет данных для чтения»: EAGAIN, что означает «попытайтесь снова позже».

• Если для записи нет места, write() либо блокируется до успешного завершения (O_NONBLOCK сброшен), либо завершается неудачей с ошибкой «в данный момент нет места для записи»: EAGAIN.

• Когда место есть, будет записано столько данных, сколько возможно, так что в конечном счете все данные будут переписаны.

Подводя итог, если вы собираетесь использовать неблокирующий ввод/вывод, любой код, который использует write(), должен быть способен обработать укороченную запись, когда успешно записан меньший объем данных, чем было затребовано. Устойчивый код в любом случае должен быть написан таким способом: даже в случае обычного файла диск может оказаться заполненным и write() сможет записать лишь часть данных.

Более того, вы должны быть готовы обработать EAGAIN, понимая, что в этом случае неудача write() не обязательно означает фатальную ошибку. То же верно для кода, использующего для чтения неблокирующий ввод/вывод: признайте, что и здесь EAGAIN не является фатальным. (Однако, может стоит подсчитывать число таких отказов, оставив попытки, когда их слишком много.)

Перейти на страницу:

Похожие книги