Как описано для обычных каналов, вызов read()
O_NONBLOCK в данном случае неуместен. Для read(fd, buf, count) и сброшенный O_NONBLOCK
Функция read()
read(fd, buf, count) и установленный O_NONBLOCK
Функция read()
errno EAGAIN.В заключение, поведение write()
константу 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
| размер ≥ nbytes | размер < abytes | |
|---|---|---|
nbytes ≤ PIPE_BUF | write() успешна | write() возвращает (-1)/EAGAIN |
| размер > 0 | размер = 0 | |
nbytes > PIPE_BUF | write() записывает, что может | write() возвращает (-1)/EAGAIN |
Для файлов, не являющихся каналами и FIFO и к которым может быть применен O_NONBLOCK
размер > 0 write()
размер = 0 write()
-1/EAGAINХотя есть ряд сбивающих с толку изменений поведения в зависимости от того, канал это или не канал, установлен O_NONBLOCK
• Всегда можно отличить конец файла: read()
• Если нет доступных для чтения данных, read()
EAGAIN, что означает «попытайтесь снова позже».• Если для записи нет места, write()
O_NONBLOCK сброшен), либо завершается неудачей с ошибкой «в данный момент нет места для записи»: EAGAIN.• Когда место есть, будет записано столько данных, сколько возможно, так что в конечном счете все данные будут переписаны.
Подводя итог, если вы собираетесь использовать неблокирующий ввод/вывод, любой код, который использует write()
write() сможет записать лишь часть данных.Более того, вы должны быть готовы обработать EAGAIN
write() не обязательно означает фатальную ошибку. То же верно для кода, использующего для чтения неблокирующий ввод/вывод: признайте, что и здесь EAGAIN не является фатальным. (Однако, может стоит подсчитывать число таких отказов, оставив попытки, когда их слишком много.)