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» байтов были фактически записаны, потому что файл находится в хорошем состоянии, то есть он состоит из целых, связных записей. Итак, первая запись не написана частично.
— Тодд Фрид
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.