Feuert inotify eine Benachrichtigung ab, wenn ein Schreibvorgang gestartet oder abgeschlossen wird?

12

Stellen Sie sich zwei Prozesse vor, einen Reader und einen Writer, die über eine reguläre Datei auf einer ext3-Fs kommunizieren. Leser hat eine inotify IN_MODIFYUhr auf der Akte. Writer schreibt 1000 Bytes in einem einzigen write()Aufruf in die Datei . Der Reader erhält das Ereignis inotify und ruft fstatdie Datei auf. Was sieht der Leser?

  1. Gibt es eine Garantie, dass Reader mindestens 1000 für st_sizedie Datei zurückerhält ? Aus meinen Experimenten scheint es nicht.

  2. Gibt es eine Garantie, dass Reader tatsächlich read()1000 Bytes kann?

Dies geschieht auf einer ernsthaften E / A-gebundenen Box. Zum Beispiel sarzeigt eine Wartezeit von ca. 1 Sekunde. In meinem Fall wartet der Reader tatsächlich 10 Sekunden, nachdem er das Inotify-Ereignis erhalten hat, bevor er anruft stat, und erhält zu kleine Ergebnisse.

Ich hatte gehofft, dass das inotify-Ereignis erst zugestellt wird, wenn die Datei fertig ist. Was ich vermute, passiert tatsächlich, dass das Ereignis inotify WÄHREND des write()Aufrufs im Writer ausgelöst wird und die Daten anderen Prozessen auf dem System tatsächlich zur Verfügung stehen, wenn sie bereit sind. In diesem Fall reichen 10s nicht aus.

Ich schätze, ich suche nur nach einer Bestätigung, dass der Kernel tatsächlich so implementiert, wie ich es mir vorstelle. Gibt es auch Optionen, um dieses Verhalten zu ändern?

Was ist der Grund für eine Inotifizierung angesichts dieses Verhaltens? Sie müssen die Datei / das Verzeichnis sowieso abrufen, nachdem Sie das Ereignis erhalten haben, bis die Daten tatsächlich verfügbar sind. Könnte das auch die ganze Zeit tun und die Inotifizierung vergessen.

*** BEARBEITEN ** * * Okay, wie so oft macht das Verhalten, das ich sehe, Sinn, jetzt, wo ich verstehe, was ich wirklich tue. ^ _ ^

Ich antworte tatsächlich auf ein IN_CREATE-Ereignis in dem Verzeichnis, in dem sich die Datei befindet. Daher stat () ich die Datei tatsächlich als Antwort auf die Erstellung der Datei, nicht unbedingt auf das IN_MODIFY-Ereignis, das möglicherweise später eintrifft.

Ich werde meinen Code so ändern, dass ich, sobald ich das Ereignis IN_CREATE erhalte, IN_MODIFY für die Datei selbst abonniere und erst dann versuche, die Datei zu lesen, wenn ich das Ereignis IN_MODIFY erhalte. Mir ist klar, dass es dort ein kleines Fenster gibt, in dem ich möglicherweise einen Schreibvorgang in die Datei verpasse. Dies ist jedoch für meine Anwendung akzeptabel, da die Datei im schlimmsten Fall nach einer maximalen Anzahl von Sekunden geschlossen wird.

Todd befreit
quelle
Sie könnten eine Pipe anstelle einer Datei verwenden. Siehe man mknod
daniel kullmann
Wir müssen eine reguläre Datei verwenden, um einen Puffer von mehreren Terabyte zwischen den beiden Prozessen zu haben. Auch um Daten im Puffer während des Neustarts zu erhalten.
Todd befreit

Antworten:

5

Von dem, was ich in der sehe Kernel - Quelle , inotify nur bis abfeuert , nachdem ein Schreiben abgeschlossen ist (dh Ihre Vermutung ist falsch). Nachdem die Benachrichtigung ausgelöst wurde, passieren nur noch zwei Dinge in sys_writeder Funktion, die den writeSystemaufruf implementiert : Festlegen einiger Scheduler-Parameter und Aktualisieren der Position im Dateideskriptor. Dieser Code ist seit 2.6.14 ähnlich . Zum Zeitpunkt des Auslösens der Benachrichtigung hat die Datei bereits ihre neue Größe.

Prüfen Sie, ob Probleme auftreten können:

  • Möglicherweise erhält der Leser alte Benachrichtigungen vom vorherigen Schreiben.
  • Wenn der Leser anruft statund dann anruft readoder umgekehrt, kann zwischendurch etwas passieren. Wenn Sie weiterhin an die Datei anhängen und statzuerst anrufen, ist sichergestellt, dass Sie bis zu diesem Zeitpunkt lesen können. Es ist jedoch möglich, dass bis zum Aufruf des Readers weitere Daten geschrieben wurden read, auch wenn die Benachrichtigung über Inotify noch nicht eingegangen ist.
  • Nur weil der Writer aufruft, writeheißt das nicht, dass der Kernel die angeforderte Anzahl von Zeichen schreibt. Es gibt nur sehr wenige Fälle, in denen atomare Schreibvorgänge bis zu einer beliebigen Größe garantiert sind. Jeder writeAufruf ist jedoch atomar garantiert: Irgendwann sind die Daten noch nicht geschrieben, und dann wurden plötzlich n Bytes geschrieben, wobei n der Rückgabewert des writeAufrufs ist. Wenn Sie eine teilweise geschriebene Datei beobachten, bedeutet dies, dass writeweniger als ihr Größenargument zurückgegeben wurde.

Zu den nützlichen Tools für die Untersuchung der Vorgänge gehören:

  • strace -tt
  • das auditd-Subsystem
Gilles 'SO - hör auf böse zu sein'
quelle
Danke für die Ideen. Ich habe gerade den Code überprüft, und ich überprüfe tatsächlich nur für -1 als den Rückgabewert vom Schreiben für den Fehlerfall. Es kann also sein, dass ich beim Schreiben nicht den Rückgabewert erhalte, der angibt, dass alle Daten geschrieben wurden. Wenn ich mir die Datei jedoch nachträglich anschaue, weiß ich, dass alle "1000" Bytes tatsächlich geschrieben wurden, weil die Datei in gutem Zustand ist, dh aus ganzen, zusammenhängenden Datensätzen besteht. Die erste Aufzeichnung wird also nicht teilweise geschrieben.
Todd befreit