fsync()
は内部でfflush()
するので、ストリームでfsync()
を使用しても問題ないと思いました。しかし、ネットワークI/Oで実行すると予期しない結果が得られます。
私のコードスニペット:
_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);
_
しかし、_commit()
はデータをフラッシュしていないようです(Windowsで試しましたが、データはLinuxのエクスポートされたファイルシステムで書き込まれました)。
コードを次のように変更したとき:
_FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
_
データをフラッシュします。
_commit()
がfflush()
と同じことをしているかどうか疑問に思っています。入力はありますか?
fflush()
はFILE*
で動作し、アプリケーションのFILE*
にある内部バッファーをOSにフラッシュするだけです。
fsync
はより低いレベルで動作し、OSにバッファーを物理メディアにフラッシュするように指示します。
OSは、ファイルに書き込むデータを大量にキャッシュします。 OSがすべての書き込みを強制してドライブにヒットした場合、事態は非常に遅くなります。 fsync
(特に)を使用すると、データがドライブにヒットするタイミングを制御できます。
さらに、fsync/commitはファイル記述子に対して機能します。 FILE*
の知識がなく、バッファをフラッシュできません。 FILE*
はアプリケーションに存在し、ファイル記述子は通常OSカーネルに存在します。
標準C関数fflush()
とPOSIXシステムコールfsync()
は、概念的には多少似ています。 fflush()
はCファイルストリーム(FILE
オブジェクト)で動作するため、移植性があります。 fsync()
POSIXファイル記述子を操作します。どちらもバッファされたデータを宛先に送信します。
POSIXシステムでは、各Cファイルストリーム 関連するファイル記述子があります であり、必要に応じてファイル記述子を操作するPOSIXシステムコールに委任することにより、Cファイルストリームに対するすべての操作が実装されます。
POSIXシステムでfflush
を呼び出すと、ファイルストリームのバッファ内のデータのwrite
が発生し、その後にfsync()
が呼び出されると考えるかもしれません。そのファイルストリームのファイル記述子。そのため、POSIXシステムでは、fflush
への呼び出しとfsync(fileno(fp))
への呼び出しに従う必要はありません。しかし、その場合は:fsync
からfflush
への呼び出しがありますか?
いいえ、POSIXシステムでfflush
を呼び出しても、fsync
が呼び出されるとは限りません。
fflush
のC標準では、(強調を追加して)
[the]ストリームの未書き込みデータがホスト環境に配信されますto be writtenファイルに
データがisであるというよりもto beであると言うことは、ホスト環境によるさらなるバッファリングが許可されることを意味します。 「ホスト環境」によるそのバッファリングには、POSIX環境の場合、fsync
がフラッシュする内部バッファリングが含まれます。したがって、C標準をよく読むと、標準ではfsync
を呼び出すためにPOSIX実装を必要としないことが示唆されています。
POSIX標準のfflush
の説明 は、 Cセマンティクスの拡張 として、fsync
が呼び出されることを宣言しません。
私はそれを簡単にするために言うことができます:
fsync()
をストリーミングファイル(整数ファイル記述子)なしで使用します
ファイルストリームでfflush()
を使用します。
また、ここに人からの助けがあります:
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()
とfsync()
を使用して、データがストレージメディアに書き込まれるようにすることができます(ただし、常に可能であるとは限りません)。
fflush(fp)
(fp
はfopen
または標準ストリームstdout
またはstderr
のいずれかから取得したFILE *
である)を使用して、ストリームに関連付けられたバッファーの内容をOSに書き込みます。fsync(fileno(fp))
を使用して、独自のバッファをストレージメディアに書き込むようOSに指示します。ただし、fileno()
およびfsync()
はPOSIX関数であり、すべてのシステム、特に代替が_fileno()
、_fsync()
または_commit()
...
以下のドキュメントからpython( https://docs.python.org/2/library/os.html )がそれを非常に明確にしていると思います。
os.fsync(fd)filedescriptor fdを使用してファイルをディスクに強制的に書き込みます。 Unixでは、これはネイティブのfsync()関数を呼び出します。 Windowsでは、MS _commit()関数。
Python file object f)で開始する場合、最初にf.flush()を実行し、次にos.fsync(f.fileno())を実行して、すべての内部バッファーが関連付けられていることを確認しますfがディスクに書き込まれます。
可用性:Unix、および2.2.3以降のWindows。
ディスクへの最近の変更のコミットを強制するには、sync()またはfsync()関数を使用します。
fsync()は、指定されたファイルのすべてのデータとメタデータを永続ストレージデバイスと同期します。対応するファイルを閉じる直前に呼び出す必要があります。
sync()は、変更されたすべてのファイルをディスクにコミットします。