read () из файлов – блокировка против неблокирующего поведения

Предположим, мы открыли файл, используя fopen() и из полученного указателя файла fileno() файл-дескриптор, используя fileno() . Затем мы делаем много (> 10 ^ 8) случайных read() s относительных небольших кусков, размером от 4Bytes до 10KBytes из этого файла:

Ожидается ли такое поведение, при котором read() может возвращать меньшее количество байтов, которые затем запрашиваются, без установки errno , если файловая система является

  1. ext3

  2. NFS

  3. OCFS2

  4. комбинация 2 и 3 ( OCFS2 через NFS )

?

Мои показания дали мне вывод, что это не должно быть возможно для 1. (если файл не установил O_NONBLOCK , если это возможно для ext3 чтобы установить его), но для остальных трех (2., 3., 4.) неопределенный.

(Btw: Могу ли я предположить, что O_NONBLOCK не будет использоваться по умолчанию в любом случае?)

Эти вопросы возникли из-за того, что я заметил, что read() s возвращает меньше байтов, а затем запрошен без errno установленных в случае 4.

Проблема, связанная с этим, заключается в том, что такое поведение происходит в случаях <1/1000000000 … – это слишком часто: -}

Обновление : средний размер файла составляет от нескольких TBytes и около 1GByte.

Вы не должны предполагать, что read () не будет возвращать меньше байтов, чем запрошено для любой файловой системы. Это особенно верно в случае больших чтений, поскольку POSIX.1 указывает, что поведение read () для размеров, больших, чем SSIZE_MAX, зависит от реализации. В этом основном ядре Unix, которое я использую прямо сейчас, SSIZE_MAX составляет 32767 байт. Тот факт, что read () всегда возвращает полную сумму сегодня, не означает, что он будет в будущем.

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

Мы решили проблему, описанную как read() возвращающее меньше байтов, а затем запрос при чтении из файла, расположенного на монте NFS , указывающего на файловую систему OCFS2 (случай 4 в моем вопросе).

Это факт, что с использованием вышеупомянутой установки такие read() s в дескрипторах файлов иногда возвращают меньшее количество байтов, которые затем запрашиваются, без установки errno .

Чтобы все данные были прочитаны, это просто, как просто read() снова и снова до тех пор, пока не будет прочитано количество запрошенных данных.

Более того, такая настройка иногда приводит к сбою read() с EIO , и даже тогда простое повторное read() приводит к успеху и приходу данных.

Мой вывод: чтение через OCFS2 через NFS делает read() из файлов, которые ведут себя подобно read() ing из сокетов, что не соответствует спецификациям read() http://pubs.opengroup.org/onlinepubs/9699919799/functions/read .html :

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

Если O_NONBLOCK установлен, read () возвращает -1 и устанавливает errno в [EAGAIN].

Если O_NONBLOCK чист, read () блокирует вызывающий stream, пока некоторые данные не станут доступными.

Не нужно говорить, что мы никогда не пробовали, и даже не думали устанавливать O_NONBLOCK для описателей файлов, о которых идет речь.