короткое чтение из файловой системы, когда это может произойти?

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

Итак, мой вопрос: в Linux, в каких случаях может read(2) возвращать меньше, чем было запрошено, если чтение из открытого файла и EOF не встречается, а читаемый объем составляет максимум несколько килобайт?

Некоторые предположения:

  • Могут ли полученные сигналы прервать такое чтение, но не привести к его сбою?
  • Могут ли разные файловые системы влиять на это поведение? Есть ли что-то особенное в jffs2?

person Nakedible    schedule 27.12.2009    source источник
comment
Какие программы предполагают, что при работе с локальными файлами read(2) никогда не возвращает меньше, чем было запрошено? В общем случае это похоже на баг.   -  person Ken    schedule 27.12.2009
comment
Например, двоичный файл fstype в klibc utils. Кажется, что многие низкоуровневые программы, которые могут считать, что работают с файлами, прямо предполагают, что чтение никогда не бывает коротким.   -  person Nakedible    schedule 27.12.2009


Ответы (6)


POSIX.1-2008 гласит:

Возвращаемое значение может быть меньше nbyte, если количество байтов, оставшихся в файле, меньше nbyte, если запрос read() был прерывается сигналом, или если файл является каналом, FIFO или специальным файлом и имеет менее nbyte байтов, доступных для чтения.

Дисковые файловые системы обычно используют непрерывное чтение, что означает, что операция чтения обычно не может быть прервана сигналом. Сетевые файловые системы иногда используют прерываемое чтение, которое может возвращать частичные данные или вообще не возвращать данные. (В случае NFS это настраивается с помощью параметра монтирования intr.) Иногда они также реализуют тайм-ауты.

Имейте в виду, что даже /some/arbitrary/file/path может ссылаться на FIFO или специальный файл, поэтому то, что вы считали обычным файлом, может им не быть. Поэтому рекомендуется обрабатывать частичные чтения, даже если они маловероятны.

person mark4o    schedule 27.12.2009
comment
Спасибо. Если это правильно, то нам нужно еще немного отладить. Мы получаем подтвержденное короткое чтение в файловой системе jffs2 (которая, я думаю, не должна иметь прерываемых чтений), и файл определенно является обычным файлом. Ситуация случается не чаще одного раза в год, поэтому воспроизводимость низкая. - person Nakedible; 27.12.2009
comment
Файловой системе разрешено прерывать чтение после чтения одного блока. - person Joshua; 09.08.2011

Я должен спросить: "почему вас волнует причина"? Если чтение может вернуть количество байтов меньше запрошенного (что, как вы указываете, безусловно, может), почему бы вам не захотеть иметь дело с этой ситуацией?

person Community    schedule 27.12.2009
comment
Чтобы добавить, вы все равно будете проверять данные - так что, если они короткие, вы сразу узнаете. Иначе какой еще смысл читать? - person ; 27.12.2009
comment
Нил, я должен спросить: какое тебе дело, почему он хочет знать, как это может произойти? Даже если он имеет дело с этой ситуацией, все равно очень полезно знать, как это может произойти, например. чтобы он мог попробовать это и проверить, что его код обрабатывает это, как ожидалось. И если это не его собственный личный код, который не обрабатывает этот случай, эта информация будет необходима как часть инструкций по воспроизведению проблемы, которые должны сопровождать любой отчет об ошибке или отправку патча. - person mark4o; 27.12.2009
comment
Причина, по которой я спрашиваю, заключается в том, что мы наблюдаем такое поведение на тысячах установленных систем, и нам необходимо как можно точнее оценить, насколько распространенной будет эта проблема в долгосрочной перспективе. Понимание того, как и почему это происходит, является частью расследования. - person Nakedible; 27.12.2009
comment
Обработка коротких операций чтения является хорошей практикой для только что написанного кода. Однако предположение, что все обрабатывает короткие чтения из всех файлов, очень опасно. У большинства компаний есть устаревший код, полный вещей, о которых вы даже не хотели бы читать. Кроме того, отсутствие обработки коротких чтений, к сожалению, является очень распространенным шаблоном во многих сторонних библиотеках. Поэтому знать, когда это может произойти, почти бесполезно, потому что это помогает вам понять, где ожидать проблем. - person Paul Groke; 24.01.2020

Полученный сигнал приводит к сбою read() только в том случае, если он еще не прочитал ни одного байта. В противном случае он вернет частичные данные.

И я предполагаю, что альтернативные файловые системы действительно могут возвращать короткие чтения в других ситуациях. Например, имеет смысл (для меня) иметь сетевую файловую систему, ведущую себя точно так же, как сетевой сокет в отношении коротких чтений (= их частое использование).

person Nicolás    schedule 27.12.2009
comment
Спасибо, это было полезно! Хотя информация о прерываемых и непрерываемых файловых системах оказалась еще более полезной. - person Nakedible; 27.12.2009

Если вы действительно читаете файл, вы можете получить короткое чтение как последнее чтение перед концом файла.

Однако, как правило, лучше вести себя так, как будто ЛЮБОЕ чтение может быть коротким чтением. Если то, что вы читаете, является каналом или устройством ввода (stdin), а не файлом, вы можете получить короткое чтение всякий раз, когда ваш буфер больше, чем то, что в данный момент находится во входном буфере.

person John Knoeller    schedule 27.12.2009
comment
Под отсутствием EOF я имел в виду именно то, что это не последнее чтение перед концом файла. Кроме того, рассматриваемый файл является обычным файлом. - person Nakedible; 27.12.2009

Я не уверен, но эта ситуация может возникнуть, когда у ОС заканчиваются страницы в кэше страниц. Вы можете предположить, что в этом случае будет вызван поток очистки, но это зависит от эвристики, используемой в планировщике ввода-вывода. Эта ситуация может привести к тому, что чтение будет возвращать меньше байтов.

person Boolean    schedule 27.12.2009

То, что я всегда читал, называется «коротким чтением» и связано не с доступом к файлу read(2), а с физическим чтением сектора диска. Это происходит, когда при чтении информационной части сектора обнаруживаются менее достоверные магнитные сигналы, чем для того, чтобы сделать 512 (или 4096 или сколько угодно) байт сектора. Это делает недопустимый сектор и ошибку чтения. Что касается «когда» или, вернее, почему это происходит, скорее всего, потому, что мощность, питающая накопитель, упала во время записи этого сектора.
Может быть, read(2) заканчивается кодом физической ошибки, называемым "коротким чтением"?

person Papou    schedule 26.06.2018