Inotify запускает уведомление, когда запись начинается или когда она завершена?

12

Представьте себе два процесса, читателя и писателя, общающихся через обычный файл на ext3 fs. Читатель имеет IN_MODIFYчасы inotify на файл. Writer записывает 1000 байтов в файл за один write()вызов. Читатель получает событие inotify и вызывает fstatфайл. Что видит Reader?

  1. Есть ли гарантия, что Reader вернет по крайней мере 1000 фунтов за st_sizeфайл? Из моих экспериментов, похоже, нет.

  2. Есть ли гарантия, что Reader может реально read()1000 байтов?

Это происходит в поле ввода / вывода с серьезными ограничениями. Например, sarпоказывает время ожидания около 1 секунды. В моем случае Reader фактически ждет 10 секунд ПОСЛЕ получения события inotify перед вызовом statи получения слишком маленьких результатов.

Я надеялся, что событие inotify не будет доставлено, пока файл не будет готов. Я подозреваю, что на самом деле происходит то, что событие inotify запускается во время write()вызова в Writer, и данные фактически становятся доступными для других процессов в системе, когда они оказываются готовыми. В этом случае 10 секунд не достаточно времени.

Я думаю, я просто ищу подтверждение того, что ядро ​​фактически реализует inotify так, как я предполагаю. Кроме того, если есть какие-либо варианты, возможно, изменить это поведение?

Наконец, какой смысл inotify, учитывая это поведение? Вы все равно должны опрашивать файл / каталог после получения события, пока данные не станут фактически доступными. С таким же успехом можно делать это все время и забыть об inotify.

*** РЕДАКТИРОВАТЬ ** * * Хорошо, как часто бывает, поведение, которое я вижу, действительно имеет смысл, теперь, когда я понимаю, что я на самом деле делаю. ^ _ ^

На самом деле я отвечаю на событие IN_CREATE в каталоге, в котором находится файл. Поэтому я на самом деле stat () обрабатываю файл в ответ на создание файла, а не обязательно на событие IN_MODIFY, которое может появиться позже.

Я собираюсь изменить свой код так, чтобы после получения события IN_CREATE я подписывался на IN_MODIFY для самого файла и фактически не пытался прочитать файл, пока не получу событие IN_MODIFY. Я понимаю, что там есть небольшое окно, в котором я могу пропустить запись в файл, но это приемлемо для моего приложения, потому что в худшем случае файл будет закрыт через максимальное количество секунд.

Тодд Фрид
источник
Вы можете использовать трубу вместо файла. Видеть, что человек MKNOD
Даниэль Kullmann
Нам нужно использовать обычный файл для того, чтобы между двумя процессами был буфер размером в несколько терабайт. Также для сохранения данных в буфере при перезагрузке.
Тодд Фрид

Ответы:

5

Из того, что я вижу в исходном коде ядра , inotify запускается только после завершения записи (т. Е. Ваше предположение неверно). После того, как уведомление инициировано, происходит только две вещи sys_write, функция, которая реализует writeсистемный вызов: установка некоторых параметров планировщика и обновление позиции в дескрипторе файла. Этот код был похож на 2.6.14 . Ко времени срабатывания уведомления файл уже имеет новый размер.

Проверьте, что может пойти не так:

  • Возможно, читатель получает старые уведомления от предыдущей записи.
  • Если читатель звонит, statа затем звонит readили наоборот, что-то может произойти между ними. Если вы продолжаете добавлять к файлу, вызов statfirst гарантирует, что вы сможете прочитать это далеко, но возможно, что к моменту вызова читателя будет записано больше данных read, даже если он еще не получил уведомление inotify.
  • Тот writeфакт, что программа записи вызывает , не означает, что ядро ​​запишет запрошенное количество символов. Есть очень немного обстоятельств, когда атомарные записи гарантированы до любого размера. Однако каждый writeвызов гарантированно атомарен: в какой-то момент данные еще не записаны, а затем внезапно записано n байтов, где n - возвращаемое значение writeвызова. Если вы наблюдаете частично записанный файл, это значит, что writeвозвращено меньше его аргумента размера.

Полезные инструменты для расследования происходящего включают в себя:

  • strace -tt
  • подсистема аудита
Жиль "ТАК - перестань быть злым"
источник
Спасибо за идеи. Я только что просмотрел код, и на самом деле я проверяю только -1 как возвращаемое значение от write для случая ошибки. Таким образом, может случиться так, что я не получаю возвращаемое значение от записи, указывающее, что все данные были записаны. Тем не менее, когда я смотрю на файл после факта, я знаю, что все «1000» байтов были фактически записаны, потому что файл находится в хорошем состоянии, то есть он состоит из целых, связных записей. Итак, первая запись не написана частично.
Тодд Фрид