Чи ініціює активація сповіщення, коли запис починається або коли воно завершено?


12

Уявіть два процеси: читач і автор, які спілкуються через звичайний файл на файлі ext3. IN_MODIFYУ файлі Reader є інотифікований годинник. Writer записує 1000 байтів у файл за один write()виклик. Читач отримує подію ініціювання та викликає fstatфайл. Що бачить Читач?

  1. Чи є гарантія, що Reader отримає принаймні 1000 для st_sizeфайлу? З моїх експериментів, схоже, ні.

  2. Чи є гарантія, що Reader може насправді read()1000 байт?

Це відбувається на серйозно пов'язаному коду вводу / виводу. Наприклад, sarпоказує час очікування близько 1 секунди. У моєму випадку "Читач" насправді чекає 10 секунд ПІСЛЯ отримання ініціативної події перед викликом statта отримання занадто малих результатів.

Я сподівався, що ініціативна подія не буде доставлена, поки файл не буде готовий. Я підозрюю, що насправді відбувається це те, що ініціативна подія спрацьовує під час write()виклику в програмі Writer, а дані фактично доступні для інших процесів у системі, коли це стане готовим. У цьому випадку 10-х - це недостатньо часу.

Я думаю, я просто шукаю підтвердження того, що ядро ​​насправді реалізує ініціювати так, як я здогадуюсь. Також, якщо є якісь варіанти, щоб змінити таку поведінку?

Нарешті - який сенс ініціювати, враховуючи таку поведінку? Після отримання події ви все одно обмежуєтесь опитуванням файлу / каталогу, поки дані фактично не стануть доступними. Можна також робити це весь час і забувати про започаткування.

*** EDIT ** * * Добре, як це часто буває, поведінка, яку я бачу, насправді має сенс, тепер, коли я розумію, що я насправді роблю. ^ _ ^

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

Я збираюся змінити свій код, щоб після отримання події IN_CREATE я підписався на IN_MODIFY на сам файл, і я фактично не намагатимусь прочитати файл, поки не отримаю подію IN_MODIFY. Я усвідомлюю, що там є невелике вікно, в якому я можу пропустити запис у файл, але це прийнятно для моєї програми, оскільки в гіршому випадку файл буде закритий через максимальну кількість секунд.


Ви можете використовувати трубу замість файлу. Дивіться man mknod
daniel kullmann

Нам потрібно використовувати звичайний файл, щоб між двома процесами був буфер декількох терабайт. Також для збереження даних у буфері при перезавантаженні.
Тодд Фрід

Відповіді:


5

З того, що я бачу у джерелі ядра , inotify запускається лише після завершення запису (тобто ваша здогадка неправильна). Після запуску повідомлення відбувається sys_writeфункція, яка реалізує writesyscall , лише дві речі : встановлення деяких параметрів планувальника та оновлення позиції в дескрипторі файлу. Цей код був подібний ще 2.6.14 . На момент запуску сповіщення файл вже має новий розмір.

Перевірте, що може піти не так:

  • Можливо, читач отримує старі сповіщення, від попереднього запису.
  • Якщо читач дзвонить, statа потім дзвонить readабо навпаки, між ними може статися щось. Якщо ви продовжуєте додавати файл, виклик statспочатку гарантує, що ви зможете прочитати так далеко, але можливо, що більше даних було записано до моменту, коли читач дзвонить read, навіть якщо він ще не отримав повідомлення про ініціативу.
  • Тільки тому, що автор викликає, writeце не означає, що ядро ​​запише потрібну кількість символів. Є дуже мало обставин, коли атомні записи гарантуються до будь-якого розміру. writeОднак кожен виклик гарантовано атомний: у якийсь момент дані ще не записуються, а потім раптом записані n байти, де n - повернене значення writeвиклику. Якщо ви спостерігаєте частково записаний файл, це означає, що writeповернуто менше аргументу його розміру.

Корисні інструменти для дослідження того, що відбувається, включають:

  • strace -tt
  • підсистема аудиту

Дякую за ідеї. Я щойно переглянув код, і насправді я лише перевіряю -1 як повернене значення з запису для випадку помилки. Отже, можливо, я не отримую значення повернення від запису, що вказує на те, що всі дані були записані. Тим не менш, коли я дивлюся на файл після факту, я знаю, що всі "1000" байтів насправді були написані, оскільки файл знаходиться в хорошій формі, тобто складається з цілих, когерентних записів. Тож перший запис частково не пишеться.
Тодд Фрід
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.