При каких обстоятельствах команда read() syscall возвращает 0?
Я просматриваю read
syscall в Unix, который (по крайней мере, в Linux) имеет эту подпись: [1]
ssize_t read(int fd, void* buf, size_t count);
Предположим, что вызов преуспевает (т.е. Отрицательные значения возврата) и что count > 0
(т.е. Буфер фактически может хранить ненулевое количество байтов). При каких обстоятельствах будет read()
return 0? Я могу думать о следующем:
- Когда
fd
ссылается на обычный файл, и конец файла достигнут. - Когда
fd
относится к принимающему концу трубы, гнезда или FIFO, конец отправки был закрыт, а собственный буфер/внутренний/внутренний порт FIFO был исчерпан. - Когда
fd
ссылается на подчиненную сторону терминального устройства, которое находится в ICANON
а Ctrl-D
отправляется на главную сторону, в то время как буфер строки пуст.
Мне любопытно, есть ли другие ситуации, о которых я не знаю, где read()
вернется с результатом 0. Мне особенно интересно (по причинам) в ситуациях, подобных последнему в списке выше, где read()
возвращает 0 один раз, но последующие вызовы read()
на том же FD могут возвращать ненулевой результат. Если ответ относится только к определенному вкусу Unix, мне все равно интересно его услышать.
[1] Я знаю, что эта подпись предназначена для оболочки libc, а не для самонастройки, но это не важно сейчас.
Ответы
Ответ 1
- Если физическая файловая система не поддерживает простые чтения из каталогов, read() вернет 0, если она используется для каталога. Вместо этого пользователи должны использовать Opendir() и readdir().
- Если ни один процесс не имеет открытого канала для записи, read() возвращает 0, чтобы указать конец файла.
- Если соединение отключено в потоковом сокете, но данных нет, функция read() возвращает 0 байтов как EOF.
Ответ 2
Обычно возвращаемое значение 0
всегда означает конец файла. Однако, если вы укажете 0
как количество прочитанных байтов, оно всегда будет возвращать 0
если не будет обнаружена ошибка.
Терминальные устройства - особый случай. Если терминал находится в режиме приготовления, введите Control-d, чтобы драйвер устройства возвращался из любого ожидающего read()
сразу с тем, что находится в буфере редактирования ввода, вместо того, чтобы ждать ввода пользователем новой строки. Если буфер пуст, это приводит к чтению с нулевой длиной. Таким образом, ввод символа EOF в начале строки автоматически обрабатывается приложениями EOF.