Der Unterschied zwischen Fflush und fsync
Frage
Ich dachte, fsync()
tut fflush()
intern, so auf einen Stream mit fsync()
ist OK. Aber ich bin immer ein unerwartetes Ergebnis, wenn unter Netzwerk-I / O ausgeführt.
Ihr Code-Snippet:
FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* get fd of the FILE pointer */
fd = fileno(fp);
#ifndef WIN32
ret = fsync(fd);
#else
ret = _commit(fd);
fclose(fp);
Aber es scheint _commit()
werden die Daten nicht Spülung (Ich habe versucht, auf Windows und die Daten geschrieben wurde auf einem Linux-Dateisystem exportiert).
Wenn ich den Code geändert werden:
FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
es spült die Daten.
Ich frage mich, ob _commit()
die gleiche Sache wie fflush()
tut. Irgendwelche Eingänge?
Lösung
fflush()
arbeitet auf FILE*
, es spült nur die internen Puffer in der FILE*
Ihrer Anwendung heraus an das OS.
fsync
Arbeiten auf einem niedrigeren Niveau, es weist das Betriebssystem seine Puffer zu den physikalischen Medien zu spülen.
OSs cachen stark Daten, die Sie in eine Datei schreiben. Wenn das Betriebssystem alle Schreib treffen den Antrieb erzwungen, würde die Dinge sein sehr langsam. fsync
(unter anderem) können Sie steuern, wenn die Daten des Antriebs treffen sollte.
Darüber hinaus fsync / commit Arbeiten auf einem Dateideskriptor. Es hat keine Kenntnis von einer FILE*
und kann seine Puffer nicht leeren. FILE*
Leben in Ihrer Anwendung, lebt Dateideskriptoren in dem OS-Kernel, in der Regel.
Andere Tipps
Die Standard-C-Funktion fflush()
und das POSIX-Systemaufruf fsync()
sind vom Konzept her ein wenig ähnlich. fflush()
arbeitet auf C-Datei-Streams (FILE
Objekte), und ist daher tragbar.
fsync()
arbeiten auf POSIX-Dateibeschreibungen.
Beiden Ursachen gepufferten Daten an einen Empfänger gesendet werden.
Auf einem POSIX-System, jeder C Datei-Stream hat eine zugehörige Dateideskriptor , und alle Operationen auf einem C-Datei-Stream werden durch die Delegation bei Bedarf zu POSIX-Systemaufrufen implementiert werden, die auf dem Dateideskriptor arbeiten.
Man könnte meinen, dass ein Aufruf fflush
auf einem POSIX-System in dem Puffer des Datei-Stream, einen write
von Daten durch einen Aufruf von fsync()
für den Dateideskriptor der Datei Stream verursachen würde. So auf einem POSIX-System würde es keine Notwendigkeit, einen Anruf zu fflush
mit einem Aufruf an fsync(fileno(fp))
zu folgen. Aber ist das der Fall: es ist ein Aufruf an fsync
von fflush
Nein, auf einem POSIX-System fflush
Aufruf bedeutet nicht, dass fsync
aufgerufen werden.
Der C-Standard für fflush
sagt (Hervorhebung hinzugefügt) es
bewirkt, dass alle ungeschriebenen Daten für [den] Strom an die Host-Umgebung geliefert werden geschrieben werden in die Datei
Zu sagen, dass die Daten sein geschrieben, anstatt das ist ist geschrieben bedeutet, dass weitere Pufferung von der Host-Umgebung erlaubt. Die durch die „Host-Umgebung“ Pufferung könnte, für eine POSIX-Umgebung, die interne Pufferung, dass fsync
Wallungen. So eine genaue Lektüre der C-Norm legt nahe, dass die Norm nicht die POSIX-Implementierung Aufruf fsync
erfordert.
Die POSIX-Standard Beschreibung fflush
erklärt nicht, wie eine Erweiterung der C-Semantik , dass fsync
genannt wird.
Ich könnte sagen, dass der Einfachheit halber:
Verwendung fsync()
mit nicht Streaming-Dateien (integer Filedeskriptoren)
Verwendung fflush()
mit Datei-Streams.
Auch hier ist die Hilfe von Menschen:
int fflush(FILE *stream); // flush a stream, FILE* type
int fsync(int fd); // synchronize a file's in-core state with storage device
// int type
fflush()
und fsync()
können verwendet werden, um Daten zu versuchen und sicherzustellen, auf das Speichermedium geschrieben sind (aber es ist nicht immer möglich sein):
- ersten Gebrauch
fflush(fp)
auf dem Ausgangsstrom (afp
FILE *
ausfopen
oder eine der Standardströmestdout
oderstderr
erhalten wird), um die Inhalte des Puffers mit dem Strom an das OS zugeordnet zu schreiben. - dann
fsync(fileno(fp))
verwendet das Betriebssystem zu sagen, seine eigenen Puffer auf das Speichermedium zu schreiben.
Beachten Sie jedoch, dass fileno()
und fsync()
POSIX-Funktionen, die nicht auf allen Systemen verfügbar sein könnten, insbesondere Microsoft Legacy-Systemen, in denen Alternativen _fileno()
genannt werden können, _fsync()
oder _commit()
...
Um das Engagement der letzten Änderungen auf der Festplatte zu erzwingen, verwenden Sie die sync () oder fsync () Funktionen.
fsync () werden alle der angegebene Datei der Daten und Metadaten mit dem permanenten Speichergerät synchronisieren. Es sollte nur aufgerufen werden, bevor die entsprechende Datei geschlossen wurde.
sync () werden alle geänderten Dateien auf die Festplatte begehen.
Ich denke, unter Dokument von Python ( https://docs.python.org/ 2 / library / os.html ) stellt klar, es sehr gut.
os.fsync (fd) Force-Schreiben von Datei mit FileDescriptor auf der Festplatte fd. Auf Unix, dies ruft die native fsync () Funktion; unter Windows die MS _commit () Funktion.
Wenn Sie mit einem Python-Datei-Objekt f fangen, erster f.flush tun (), und dann tun os.fsync (f.fileno ()), um sicherzustellen, dass alle internen Puffer im Zusammenhang mit f auf der Festplatte geschrieben werden.
Verfügbarkeit:. Unix und Windows in 2.2.3 Start