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_MODIFY
Uhr auf der Akte. Writer schreibt 1000 Bytes in einem einzigen write()
Aufruf in die Datei . Der Reader erhält das Ereignis inotify und ruft fstat
die Datei auf. Was sieht der Leser?
Gibt es eine Garantie, dass Reader mindestens 1000 für
st_size
die Datei zurückerhält ? Aus meinen Experimenten scheint es nicht.Gibt es eine Garantie, dass Reader tatsächlich
read()
1000 Bytes kann?
Dies geschieht auf einer ernsthaften E / A-gebundenen Box. Zum Beispiel sar
zeigt 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.
Antworten:
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_write
der Funktion, die denwrite
Systemaufruf 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:
stat
und dann anruftread
oder umgekehrt, kann zwischendurch etwas passieren. Wenn Sie weiterhin an die Datei anhängen undstat
zuerst 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 wurdenread
, auch wenn die Benachrichtigung über Inotify noch nicht eingegangen ist.write
heiß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. Jederwrite
Aufruf ist jedoch atomar garantiert: Irgendwann sind die Daten noch nicht geschrieben, und dann wurden plötzlich n Bytes geschrieben, wobei n der Rückgabewert deswrite
Aufrufs ist. Wenn Sie eine teilweise geschriebene Datei beobachten, bedeutet dies, dasswrite
weniger als ihr Größenargument zurückgegeben wurde.Zu den nützlichen Tools für die Untersuchung der Vorgänge gehören:
strace -tt
quelle