Ich dachte, dass fsync () intern fflush () tut, also ist die Verwendung von fsync () für einen Stream in Ordnung. Ich erhalte jedoch ein unerwartetes Ergebnis, wenn es unter Netzwerk-E/A ausgeführt wird.
Mein Code-Snippet:
FILE* fp = fopen(file,"wb");
/* multiple fputs() call 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);
Es scheint jedoch, dass _commit () die Daten nicht leert (ich habe es unter Windows versucht, und die Daten wurden unter Linux exportiert).
Wenn ich den Code geändert habe als:
FILE* fp = fopen(file,"wb");
/* multiple fputs() call like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
Diesmal werden die Daten gelöscht.
Ich frage mich, ob _commit () dasselbe tut wie fflush (). Irgendwelche eingaben?
fflush()
arbeitet mit FILE*
, es werden nur die internen Puffer im FILE*
Ihrer Anwendung an das Betriebssystem ausgegeben.
fsync
arbeitet auf einer niedrigeren Ebene und weist das Betriebssystem an, die Puffer auf die physischen Medien zu leeren.
Betriebssysteme speichern Daten, die Sie in eine Datei schreiben, stark zwischen. Wenn das Betriebssystem jeden Schreibvorgang erzwingt, um das Laufwerk zu treffen, wären die Dinge sehr langsam. fsync
(ua) ermöglicht Ihnen zu steuern, wann die Daten auf das Laufwerk gelangen.
Außerdem arbeitet fsync/commit mit einem Dateideskriptor. Es hat keine Kenntnis von einem FILE*
und kann seine Puffer nicht leeren. FILE*
lebt in Ihrer Anwendung, Dateideskriptoren befinden sich normalerweise im Betriebssystemkern.
Die Standard-C-Funktion fflush()
und der POSIX-Systemaufruf fsync()
sind konzeptionell ähnlich. fflush()
arbeitet für C-Dateistreams (FILE
-Objekte) und ist daher portabel .fsync()
für POSIX-Dateideskriptoren . Beide bewirken, dass gepufferte Daten an ein Ziel gesendet werden.
Auf einem POSIX-System verfügt jeder C-Dateistream über einen zugehörigen Dateideskriptor , und alle Vorgänge in einem C-File-Stream werden implementiert, indem erforderlichenfalls an POSIX-Systemaufrufe delegiert wird, die den Dateideskriptor bearbeiten.
Man könnte meinen, ein Aufruf von fflush
auf einem POSIX-System würde eine write
der Daten im Puffer des Dateistreams verursachen, gefolgt von einem Aufruf von fsync()
für den Dateideskriptor dieses Dateistreams. Auf einem POSIX-System ist es daher nicht erforderlich, einen Aufruf von fflush
mit einem Aufruf von fsync(fileno(fp))
zu verfolgen. Aber ist das der Fall: Gibt es einen Aufruf von fsync
an fflush
?
Nein, der Aufruf von fflush
auf einem POSIX-System bedeutet nicht, dass fsync
aufgerufen wird.
Der C-Standard für fflush
sagt (Hervorhebung hinzugefügt)
veranlasst, dass ungeschriebene Daten für den [Stream] an die Host-Umgebung geschrieben werden an die Datei übermittelt werden
Die Angabe, dass die Daten zu sein geschrieben sind, anstatt dass ist geschrieben ist, impliziert, dass weitere Pufferung durch die Host-Umgebung zulässig ist. Diese Pufferung durch die "Host-Umgebung" könnte für eine POSIX-Umgebung die interne Pufferung umfassen, die von fsync
geleert wird. Eine genaue Lektüre des C-Standards legt also nahe, dass die POSIX-Implementierung nicht für den Aufruf von fsync
erforderlich ist.
Die POSIX-Standardbeschreibung von fflush
erklärt nicht als Erweiterung der C-Semantik , dass fsync
aufgerufen wird.
Ich könnte das der Einfachheit halber sagen:
verwenden Sie fsync()
ohne Streaming-Dateien (Ganzzahl-Dateideskriptoren).
verwenden Sie fflush()
mit Dateistreams.
Auch hier ist die Hilfe des 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 sicherzustellen, dass Daten auf das Speichermedium geschrieben werden (dies ist jedoch nicht immer möglich):
fflush(fp)
für den Ausgabestream (fp
ist ein FILE *
, der aus fopen
oder einem der Standard-Streams stdout
oder stderr
), um den Inhalt des Puffers, der dem Stream zugeordnet ist, in das Betriebssystem zu schreiben.fsync(fileno(fp))
, um das Betriebssystem anzuweisen, seine eigenen Puffer auf das Speichermedium zu schreiben.Beachten Sie jedoch, dass es sich bei fileno()
und fsync()
um POSIX-Funktionen handelt, die möglicherweise nicht auf allen Systemen verfügbar sind, insbesondere bei Microsoft-Legacy-Systemen, bei denen Alternativen möglicherweise als _fileno()
, _fsync()
oder _commit()
...
Ich denke, das folgende Dokument von Python ( https://docs.python.org/2/library/os.html ) klärt es sehr gut.
os.fsync (fd) Erzwingt das Schreiben der Datei mit dem Fidesescriptor fd auf die Festplatte. Auf Unix ruft die native fsync () - Funktion auf; unter Windows die MS _commit () - Funktion.
Wenn Sie mit einem Python-Dateiobjekt f beginnen, führen Sie zuerst f.flush (), .__ aus. und führen Sie dann os.fsync (f.fileno ()) aus, um sicherzustellen, dass alle internen Puffer f zugeordnet werden, werden auf die Festplatte geschrieben.
Verfügbarkeit: Unix und Windows ab 2.2.3.
Verwenden Sie die Funktionen sync () oder fsync (), um die Übernahme der letzten Änderungen auf der Festplatte zu erzwingen.
fsync ()synchronisiert alle Daten und Metadaten der angegebenen Datei mit dem permanenten Speichergerät. Es sollte kurz vor dem Schließen der entsprechenden Datei aufgerufen werden.
sync ()schreibt alle geänderten Dateien auf die Festplatte.