Wird der Puffer automatisch auf die Festplatte geleert, wenn ein Prozess beendet wird?

21

Wenn ich die Ausgabe eines Befehls in eine Datei umleite (z. B. echo Hello > file), wird sichergestellt, dass diese Datei diese Daten unmittelbar nach dem Beenden des Befehls enthält? Oder gibt es immer noch ein sehr kleines Fenster zwischen den Befehlsexits und den in die Datei geschriebenen Daten? Ich möchte die Datei direkt nach dem Beenden des Befehls lesen, möchte aber keine leere Datei lesen.

Eric
quelle
1
Wahrscheinlich wird der Befehl sofort ausgeführt, aber die Zeit, die zum Öffnen, Schreiben und Schließen der Datei benötigt wird, hängt von der Geschwindigkeit und dem Typ Ihrer Festplatte, den ausgeführten Programmen usw. ab.
freginold 25.01.18
Was ist der Prozess in Bezug auf das gegebene Beispiel? Sind echound >nicht getrennte (kurzlebige) Prozesse? Und wo wird die Ausgabe echovonrest >ausgeführt?
25.
1
@ oɔɯǝɹ >ist die Shell-Umleitung. Es ist dasselbe, als hätte das Programm die genannte Datei zum Schreiben geöffnet und durch stdout ersetzt, was genau das ist, was die Shell tut.
Dan D.
7
Ich denke, es liegt in der Verantwortung des Betriebssystems, Ihnen das fileContaining zu geben , Hellounabhängig davon, ob es gespült wird oder nicht.
Salman A
1
Wenn das Programm auf Computer A ausgeführt wird und Sie die Datei auf Computer B lesen, während das Dateisystem von Computer A über das Netzwerk gemountet ist, wird möglicherweise eine leere Datei gelesen, abhängig vom Typ des Netzwerk-Dateisystems und den Mount-Einstellungen. Daher möchten Sie möglicherweise das Caching für diesen Mount deaktivieren.
Pkt

Antworten:

21

Es sind mehrere Schichten von Puffern / Caches beteiligt.

  1. Der CPU-Cache.

    Die Daten werden byteweise zusammengesetzt und im CPU-Cache abgelegt. Wenn der CPU-Cache voll ist und auf die Daten eine Zeit lang nicht zugegriffen wurde, wird der Block, der unsere Daten enthält, möglicherweise in den Hauptspeicher geschrieben. Diese sind größtenteils den Anwendungsprogrammierern verborgen.

  2. Die In-Process-Puffer.

    In dem Prozess, in dem die Daten gesammelt werden, ist ein Teil des Speichers reserviert, sodass wir so wenig Anforderungen wie möglich an das Betriebssystem stellen müssen, da dies vergleichsweise teuer ist. Der Prozess kopiert die Daten in diese Puffer, die wiederum von CPU-Caches gesichert werden können. Daher kann nicht garantiert werden, dass die Daten in den Hauptspeicher kopiert werden. Die Anwendung muss diese Puffer explizit leeren, z. B. mit fclose (3) oder fsync (3). Die exit (3) -Funktion tut dies auch, bevor der Prozess beendet wird, während die _exit (2) -Funktion dies nicht tut , weshalb es in der Manualpage eine große Warnung gibt, dass diese Funktion nur dann aufgerufen wird, wenn Sie wissen, was Sie sind tun.

  3. Der Kernel puffert

    Das Betriebssystem behält dann seinen eigenen Cache bei, um die Anzahl der Anforderungen zu minimieren, die es an die Festplatten senden muss. Dieser Cache gehört keinem bestimmten Prozess an, daher gehören die Daten dort möglicherweise zu Prozessen, die bereits beendet wurden. Da alle Zugriffe hier durchgeführt werden, werden die Daten dem nächsten Programm angezeigt, wenn sie hier angekommen sind. Der Kernel schreibt diese Daten auf die Datenträger, wenn er Zeit dazu hat oder wenn er ausdrücklich dazu aufgefordert wird.

  4. Der Laufwerk-Cache

    Die Laufwerke selbst haben auch einen Cache, um die Zugriffe zu beschleunigen. Diese werden relativ schnell geschrieben, und es gibt einen Befehl zum Schreiben der verbleibenden Daten in die Caches und zum Melden, wenn diese abgeschlossen sind. Das Betriebssystem verwendet diesen Befehl beim Herunterfahren, um sicherzustellen, dass keine Daten vor dem Ausschalten ungeschrieben bleiben.

Für Ihre Anwendung ist es ausreichend, dass die Daten in den Kernel-Puffern registriert sind (die tatsächlichen Daten befinden sich möglicherweise zu diesem Zeitpunkt noch in CPU-Caches und wurden möglicherweise nicht in den Hauptspeicher geschrieben): Der "Echo" -Prozess wird beendet Dies bedeutet, dass alle In-Process-Puffer geleert und die Daten an das Betriebssystem übergeben wurden. Wenn Sie dann einen neuen Prozess starten, wird garantiert, dass das Betriebssystem die gleichen Daten zurückgibt, wenn Sie dazu aufgefordert werden.

Simon Richter
quelle
7
In Anbetracht der CPU-Zwischenspeicherung scheint mir das nicht relevant zu sein. Das ist hier ein unnötiger Detaillierungsgrad. Wie würde durch alle Details gehen, bis eine physikalische Größe, die ein Bit auf einer Festplatte oder einem SSD-Speicher darstellt, geändert wird, um es umzudrehen.
MVW
3
In der Tat ist der CPU-Cache ziemlich orthogonal.
Simon Richter
2
Und was noch wichtiger ist, der CPU-Cache ist zwischen den Kernen kohärent, weshalb er völlig unübersichtlich ist. Auf x86 ist es sogar mit DMA kohärent (und x86 verfügt über einen Modus zum Ordnen des Speichers nach vollständiger Speicherreihenfolge), sodass für alle Daten, die Speicher lesen können, die Daten angezeigt werden, die zuletzt an dieser Adresse in der globalen Reihenfolge der Speicheroperationen gespeichert wurden. (Ein CPU-Kern sieht seine eigenen Stores, noch bevor sie global sichtbar werden, da sie von der Store-Warteschlange weitergeleitet werden.) Auf Nicht-x86-Plattformen ohne cachekohärenten DMA stellt der Linux-Kernel sicher, dass der Cache vor dem DMA an diese Adressen entleert wird.
Peter Cordes
1
"Diese sind größtenteils vor den Anwendungsprogrammierern verborgen." Warum "zum größten Teil"? Ich bin ein Embedded-Entwickler und außer beim Bootloader (also nicht "Anwendung") ignoriere ich den CPU-Cache vollständig. Ich glaube nicht, dass Anwendungsentwickler von den Auswirkungen des CPU-Cache betroffen sein können.
Sam
1
Bei einigen CPUs können @Sam-Cache-Fehlschläge / Treffer zusammen mit spekulativer Ausführung ausgenutzt werden, um Lesezugriffsbeschränkungen zu umgehen. Vielleicht ist es das, worauf sich die Antwort bezieht?
John Dvorak
22

Wenn die Anwendung keine internen Caches hat, werden die Änderungen sofort in die Datei geschrieben. Das gleiche gilt für dein Beispiel. Die Datei ist eine logische Einheit im Speicher, die sofort aktualisiert wird. Alle nachfolgenden Operationen an der Datei werden die vom Programm vorgenommenen Änderungen angezeigt.

Dies bedeutet jedoch nicht, dass die Änderung auf die physische Festplatte geschrieben wurde. Die Änderungen können in den Dateisystem- oder Hardware-Caches des Betriebssystems verbleiben. Verwenden Sie den syncBefehl, um die Dateisystempuffer zu leeren .

Ich möchte die Datei direkt nach dem Beenden des Befehls lesen, möchte aber keine leere Datei lesen.

Sie sollten hier auf keine praktischen Probleme stoßen.

mtak
quelle
1
"Wenn die Anwendung keine internen Caches hat" - das ist ein sehr großes "Wenn": Die überwiegende Mehrheit der E / A-Bibliotheksimplementierungen verwendet standardmäßig den Standardpuffer "stdout". Allerdings schreibt der C-Standard zum Beispiel vor, dass der stdout-Puffer beim Beenden geleert werden muss (möglicherweise jedoch nicht, wenn er exitnicht zumindest implizit aufgerufen wird). Andere Bibliotheken / Sprachen (zB Java!) Geben weniger Garantien.
Konrad Rudolph
Was ist, wenn Sie es nur auf das Umleitungsprimitiv (dh den Befehl in meiner Frage) beschränken? Es hat keine internen Caches, oder?
Eric
@Eric Nein, es sollte dir gut gehen.
Mtak
10
Ich bin mir nicht sicher, ob ich diese Antwort bekomme. Die Frage ist "wann der Prozess beendet wird". Jede Anwendung mit internen Schreib-Caches löscht sie beim Beenden des Prozesses auf die Festplatte, sofern dies nicht schon früher geschehen ist. IOW, diese Caches spielen hier keine Rolle.
MSalters
2
Außerdem wird ein interner Puffer entweder beim Beenden geleert oder nur ausgeblendet, oder? Selbst wenn die internen Puffer nicht geleert werden, ist der Inhalt nicht sichtbar, egal wie lange man warten würde.
WorldSEnder
21

Wird der Puffer automatisch auf die Festplatte geleert, wenn ein Prozess beendet wird?

Im Allgemeinen lautet die Antwort nein .

Das hängt vom Befehl ab. Wie in den anderen Antworten erwähnt, sind alle Daten verfügbar, wenn der Befehl beendet wird , wenn der Befehl die Daten nicht intern puffert.

Aber die meisten, wenn nicht alle Standard - I / O - Bibliotheken tun Puffer stdout standardmäßig (in gewissem Maße) und andere Garantien über die automatische Spülung der Puffer , wenn die Anwendung geschlossen wird .

C garantiert, dass ein normaler Ausgang die Puffer leeren wird . "Normaler Ausstieg" bedeutet, dass er exitaufgerufen wird - entweder explizit oder durch Rückkehr von main. Ein abnormaler Ausgang kann diesen Aufruf jedoch umgehen (und daher nicht gelöschte Puffer zurücklassen).

Hier ist ein einfaches Beispiel:

#include <signal.h>
#include <stdio.h>

int main() {
    printf("test");
    raise(SIGABRT);
}

Wenn Sie dies kompilieren und ausführen, testwird es nicht unbedingt in stdout geschrieben.

Andere Programmiersprachen bieten noch weniger Garantien: Java wird beispielsweise beim Beenden des Programms nicht automatisch gelöscht . Wenn der Ausgabepuffer eine nicht abgeschlossene Zeile enthält, kann er daher verloren gehen, sofern System.out.flush()er nicht explizit aufgerufen wurde.

Wie gesagt, Ihre Frage Körper fragt etwas etwas anders: Wenn die Daten in der Datei kommt überhaupt , sollte es tun so unmittelbar nach dem Befehl endet (vorbehaltlich der Einschränkungen in den anderen Antworten beschrieben).

Konrad Rudolph
quelle
7
Ich habe auch ein abnormales Beenden festgestellt, wenn ein Befehlszeilentool in eine Datei und in stdout oder stderr schreibt, wie in einem Debug-Protokoll, und der Benutzer eine Pipe an head oder weniger ausgeführt hat und dann 'q' eingibt, um weniger zu beenden. Die Festplattendatei wird nicht immer vollständig geleert, wenn das Befehlszeilentool SIGPIPE nicht verarbeitet hat.
Zan Lynx
+1, aber "das sollte sofort nach Beendigung des Befehls geschehen " ist nicht ganz richtig: Vor dem Beenden des Prozesses werden alle write()oder pwrite()Systemaufrufe ausgeführt , und dann werden die Dateiänderungen sichtbar. Die letzte Dateiänderung erfolgt also definitiv vor dem Prozessabschluss, spätestens jedoch unmittelbar davor. Ich denke, selbst bei einer Datei gibt es keine Möglichkeit, die Beendigung des Prozesses zu beobachten, bevor nicht alle Dateiänderungen vorgenommen wurden. mmap(MAP_SHARED)
Peter Cordes
9

Ich denke, dass noch keine Frage dieses Problem ausreichend anspricht:

Ich möchte die Datei direkt nach dem Beenden des Befehls lesen, möchte aber keine leere Datei lesen.

Wie die anderen Antworten erklären, leert ein gut funktionierendes Programm seine internen Dateipuffer, bevor der Prozess normal beendet wird . Danach verbleiben die Daten möglicherweise noch in Kernel- oder Hardware-Puffern, bevor sie in den dauerhaften Speicher geschrieben werden. Die Dateisystemsemantik von Linux garantiert jedoch, dass alle Prozesse den Inhalt von Dateien auf dieselbe Weise sehen wie der Kernel, einschließlich der internen Puffer 1 .

Dies wird normalerweise implementiert, indem höchstens ein Kernel-Puffer pro Dateiobjekt vorhanden ist und der gesamte Dateizugriff auf diesen Puffer erforderlich ist.

  • Wenn ein Prozess eine Datei liest, zeigt der Kernel dem Prozess den Pufferinhalt an, wenn sich der angeforderte Dateiteil derzeit im Puffer befindet. Ist dies nicht der Fall, ruft der Kernel die Daten vom zugrunde liegenden Speichermedium ab und legt sie in den Puffer. Kehren Sie dann zum vorherigen Schritt zurück.

  • Wenn ein Prozess in eine Datei schreibt, werden die Daten zuerst in den kernelinternen Puffer für diese Datei gestellt. Schließlich wird der Pufferinhalt in den Speicher gespült. In der Zwischenzeit wird der Lesezugriff aus demselben Puffer ausgeführt (siehe oben).


1 Zumindest für normale Dateien, Verzeichnisse und symbolische Links. FIFOs und Sockets sind eine andere Sache, da ihr Inhalt sowieso nie dauerhaft gespeichert wird. Es gibt einige Sonderfälle für reguläre Dateien, deren Inhalt davon abhängt, wer fragt. Beispiele sind Dateien in procfs und sysfs (denken Sie, /proc/selfdies ist eine symbolische Verknüpfung zur Prozess-ID des Prozesses, der die symbolische Verknüpfung liest).

David Foerster
quelle
2
Genau genommen ist dies nicht durch die Dateisystemsemantik von Linux gewährleistet, sondern durch die POSIX-Semantik. Insbesondere verhält sich BSD genauso wie macOS und sogar Windows (obwohl dies einer der wenigen Fälle ist, in denen Windows der POSIX-Semantik folgt). Dies setzt auch voraus, dass niemand ungerade mmap()Dinge mit und O_DIRECT macht, was dazu führen kann, dass Dinge zwischen der Festplatte und dem Seiten-Cache nicht mehr synchron sind (aber das wird den Moment beheben, in dem der Prozess, der dies tut, beendet wird).
Austin Hemmelgarn
2
@AustinHemmelgarn: Genau genommen haben wir beide Recht, da Linux mit Blick auf die Unterstützung von Unix (System V) -Anwendungen entwickelt wurde und später POSIX unterstützt, das auch viele Konzepte auf System V basiert.
David Foerster
5

Angenommen, Ihr Befehl wird von einem Programm ausgeführt, das die C-Laufzeitbibliothek verwendet, und sollte zu einem bestimmten Zeitpunkt aufgerufen werden fclose, um die geöffnete Datei zu schließen.

Die Manpage für die fcloseC-Funktion lautet:

HINWEISE Beachten Sie, dass fclose () nur die von der C-Bibliothek bereitgestellten Benutzerbereichspuffer löscht. Um sicherzustellen, dass die Daten physisch auf der Festplatte gespeichert sind, müssen auch die Kernel-Puffer geleert werden, beispielsweise mit sync (2) oder fsync (2).

und die Manpage für fflushhat den gleichen Vermerk. Die Manpage für closesagt:

Ein erfolgreicher Abschluss garantiert nicht, dass die Daten erfolgreich auf der Festplatte gespeichert wurden, da der Kernel das Schreiben verzögert. Es ist nicht üblich, dass ein Dateisystem die Puffer löscht, wenn der Stream geschlossen wird. Wenn Sie sicher sein müssen, dass die Daten physisch gespeichert sind, verwenden Sie fsync (2). (Dies hängt zu diesem Zeitpunkt von der Festplattenhardware ab.)

Beachten Sie, dass die Daten auch dann für andere Prozesse verfügbar sind, wenn sie nicht mit dem Laufwerk synchronisiert sind. Vielleicht ist das schon gut genug für dich.

Wenn Sie Zweifel haben, schreiben Sie einen Test.

mvw
quelle
2
C oder nicht, alles wird / sollte den close()Syscall verwenden, um den Deskriptor einer Datei zu schließen.
Attie
@Attie: Sie müssen nicht brauchen , um closeDateien vor (in Hacky - Programme , die auf Fehler nicht überprüfen) austritt; Der Kernel räumt sie auf und ruft closeSie nach dem Abbruch Ihres Prozesses auf. Sie müssen fclosejedoch gepufferte stdio-Streams verwenden oder libc dies für Sie erledigen lassen exit(3), im Gegensatz zum direkten Aufruf des Exitsystems.
Peter Cordes
Wenn Sie Zweifel haben, schreiben Sie einen Test. Dies ist ein schlechter Rat, um Rennbedingungen zu erkennen. Wenn Sie einen Kernel testen, der auf einer Hardware ausgeführt wird, können Sie möglicherweise feststellen, dass das Rennen unter den Softwarebedingungen, die durch den Test auf diesem System verursacht wurden, nicht stattfinden kann oder dass es zu selten ist, dies zu erkennen. Es kann Ihnen jedoch nicht sagen, ob dieses Verhalten für alle Dateisysteme, Kernel und alle Hardware (z. B. PowerPC) sicher sein soll . Sie können also nicht sagen, ob es sich bei der Garantie, von der Sie abhängig sind, um ein Implementierungsdetail oder eine beabsichtigte zukunftssichere Garantie handelt! (In diesem Fall ist es.)
Peter Cordes
Es hängt von der Situation ab. Einigen Leuten, die versuchen, sein Shell-Skript zum Laufen zu bringen, könnte dieser Ratschlag helfen. Es war nicht als allgemeine Lösung für fortgeschrittenere, aber weniger wahrscheinliche Umgebungen gedacht, z. B. für einen Softwareingenieur, der an einem Betriebssystemkernel arbeitet, für Leute, die an Intels Mikrocode-Update arbeiten, oder für einige Galeristen, die an einem System für die ISS arbeiten.
MVW
3

Wenn ich die Ausgabe eines Befehls in eine Datei umleite (z. B. echo Hello > file), wird sichergestellt, dass diese Datei diese Daten unmittelbar nach dem Beenden des Befehls enthält?

Ja. Die Shell öffnet die Ausgabedatei und echogibt diese direkt aus. Nachdem der Befehl beendet wurde, ist er fertig.

Oder gibt es immer noch ein sehr kleines Fenster zwischen den Befehlsexits und den in die Datei geschriebenen Daten?

Ob sich die Daten bereits auf dem Datenträger befinden, ist eine andere Frage, die nur bei einem späteren Hardwarefehler von Bedeutung ist, oder ob Sie die Live-Partition mit einer forensischen Software unter Umgehung des bereitgestellten Dateisystems überprüfen.

Ich möchte die Datei direkt nach dem Beenden des Befehls lesen, möchte aber keine leere Datei lesen.

Keine Sorge, der Kernel behält nur eine Ansicht der Datei, unabhängig davon, wie oft sie geöffnet wird.

Deduplizierer
quelle
"der kernel behält nur eine ansicht der datei": nicht ganz richtig für mmap(MAP_SHARED): speicher in der mmap-region stimmen nicht mit lesevorgängen der datei überein (von diesem thread oder anderen prozessen). Deshalb msync(2)gibt es. Zumindest warnen die Manpages davor; Abhängig von der Implementierung ordnet Linux möglicherweise tatsächlich physische Seiten aus dem Pagecache zu. In diesem Fall würde ich vermuten, dass dies im Grunde genommen kohärent ist (Modulo-Speicherreihenfolge). Wie auch immer, es passiert immer noch alles vorher _exit(2).
Peter Cordes
2

In der Regel werden alle Daten, die dem Kernel gehören, vom Kernel-Zeitraum verwaltet und bereinigt. Solche Daten umfassen Daten, die durch einen Systemaufruf, wie z write(2).

Allerdings, wenn Ihre Anwendung (zB C - Bibliothek) führt auf Pufferung oben von diesem, dann der Kern offensichtlich keine Ahnung hat , und daher bietet keine Garantie für ihre Reinigung.

Außerdem glaube ich nicht, dass es für die Bereinigung eine Zeitgarantie gibt - sie wird im Allgemeinen nach "bestem Vermögen" durchgeführt (sprich: "wenn ich eine Sekunde Zeit habe").

Mehrdad
quelle
Es besteht die Garantie, dass vor der waitpid()Rückkehr eines übergeordneten Prozesses eine Bereinigung / Pufferbereinigung erfolgt , sofern die Bereinigung überhaupt erfolgt. Das heißt, andere Prozesse können den Prozessabschluss nicht direkt beobachten, bevor von diesem Prozess vorgenommene Dateiänderungen vorgenommen wurden. (Ich sagte "direkt", um indirekte Beobachtung durch NFS-Datei-Zeitstempel auszuschließen, da das NFS-Caching zwischen Hosts nicht perfekt kohärent ist.)
Peter Cordes
@PeterCordes: Ich nehme an, es kommt darauf an, was Sie unter "Aufräumen" und nicht unter "Pflegen" verstehen. "Beibehalten" bedeutet für mich "eine kohärente Sichtweise" (mit der von Ihnen genannten Garantie) und "Aufräumen" bedeutet "auf die Festplatte spülen", für das ich keine Zeitgarantie habe.
Mehrdad
Oh, ich verstehe, Sie beantworten den Teil der Frage, der "auf die Festplatte gespült" wird und für die späteren Prozesse beim Lesen der Datei unerheblich ist. "aufräumen" im Sinne von "schmutzigen I / O-Cache / Pufferspeicher sauber machen". Richtig, keine Timing-Garantie, es sei denn, Sie verwenden fsync/ fdatasync, obwohl das Zurückschreiben des Puffers unter Linux nach /proc/sys/vm/dirty_writeback_centisecsHundertstelsekunden beginnt (sofern nicht durch anderen E / A-Verkehr verzögert), und verschiedene andere Tunables in diesem procfs-Verzeichnis ebenfalls Auswirkungen haben (z. B. wie) groß, um Puffer vor dem Zurückschreiben wachsen zu lassen).
Peter Cordes
2

Oder gibt es immer noch ein sehr kleines Fenster zwischen den Befehlsexits und den in die Datei geschriebenen Daten?

Nein, das gibt es nicht.

Ich möchte die Datei direkt nach dem Beenden des Befehls lesen, möchte aber keine leere Datei lesen.

Sie können den endgültigen Inhalt der Datei direkt nach dem Beenden des Befehls lesen. Stattdessen wird die leere Datei nie gelesen. (Verwenden Sie in C und C ++ die Systemaufrufe wait , waitpid , wait3 oder wait4 , um auf das Beenden des Programms zu warten und erst dann die Datei zu lesen. Wenn Sie eine Shell, eine andere Programmiersprache oder eine Bibliothek (z. B. die C-Bibliothek) verwenden call system oder die Java Process- Klasse) verwendet wahrscheinlich bereits einen dieser Systemaufrufe.)

Wie andere Antworten und Kommentare gezeigt haben, können Sie nach dem Beenden des Programms eine leere Datei lesen, wenn das Programm beendet wurde, ohne die internen Ausgabepuffer zu leeren (z. B. wegen _exit , Abbruch oder Empfang eines schwerwiegenden Signals oder weil dies der Fall ist) ein Java-Programm, das normal beendet wird). An dieser Stelle können Sie jedoch nichts dagegen tun: Die nicht gelöschten Daten gehen für immer verloren, zusätzliche Wartezeiten stellen sie nicht wieder her.

pts
quelle
0

Ja

Es tut mir leid, dass Sie vielleicht eine weitere überflüssige Antwort hinzugefügt haben, aber die meisten scheinen sich auf den roten Hering des Titels der Frage zu konzentrieren. Aber soweit ich das beurteilen kann, geht es bei der Frage überhaupt nicht um Pufferung, sondern um Folgendes:

Wenn ich die Ausgabe eines Befehls in eine Datei umleite (z. B. Echo Hello> Datei), hat diese Datei nach dem Beenden des Befehls garantiert solche Daten?

Ja, bedingungslos. Die Verwendung von ">", die Sie beschreiben, zusammen mit "|" und "<" ist das Pipe-basierte Verarbeitungsmodell, auf dem die Unix- und Linux-Welt stark basiert. In Abhängigkeit von diesem Verhalten werden Sie in jeder Linux-Installation Hunderte, wenn nicht Tausende von Skripten finden.

Es funktioniert so, wie Sie es möchten, und wenn es auch nur die geringste Chance für einen Rennzustand gegeben hätte, wäre dies wahrscheinlich vor Jahrzehnten behoben worden.

AnoE
quelle
Das ist leider überflüssig. Nur ein paar der Antworten konzentrieren sich hauptsächlich auf das Red Herring des Commitings von Daten zu nichtflüchtigen Speichern. Siehe @ pts Antwort und einige andere für eine klare Beschreibung: Änderungsdatei geschieht vor dem Verlassen, oder gar nicht.
Peter Cordes