web-dev-qa-db-ja.com

fflushとfsyncの違い

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()と同じことをしているかどうか疑問に思っています。入力はありますか?

49
Adil

fflush()FILE*で動作し、アプリケーションのFILE*にある内部バッファーをOSにフラッシュするだけです。

fsyncはより低いレベルで動作し、OSにバッファーを物理メディアにフラッシュするように指示します。

OSは、ファイルに書き込むデータを大量にキャッシュします。 OSがすべての書き込みを強制してドライブにヒットした場合、事態は非常に遅くなります。 fsync(特に)を使用すると、データがドライブにヒットするタイミングを制御できます。

さらに、fsync/commitはファイル記述子に対して機能します。 FILE*の知識がなく、バッファをフラッシュできません。 FILE*はアプリケーションに存在し、ファイル記述子は通常OSカーネルに存在します。

77
nos

標準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が呼び出されることを宣言しません。

5
Raedwald

私はそれを簡単にするために言うことができます:

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
2
pulse

fflush()fsync()を使用して、データがストレージメディアに書き込まれるようにすることができます(ただし、常に可能であるとは限りません)。

  1. 最初に出力ストリームでfflush(fp)fpfopenまたは標準ストリームstdoutまたはstderrのいずれかから取得したFILE *である)を使用して、ストリームに関連付けられたバッファーの内容をOSに書き込みます。
  2. 次に、fsync(fileno(fp))を使用して、独自のバッファをストレージメディアに書き込むようOSに指示します。

ただし、fileno()およびfsync()はPOSIX関数であり、すべてのシステム、特に代替が_fileno()_fsync()または_commit()...

0
chqrlie

以下のドキュメントから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。

0
poordeveloper

ディスクへの最近の変更のコミットを強制するには、sync()またはfsync()関数を使用します。

fsync()は、指定されたファイルのすべてのデータとメタデータを永続ストレージデバイスと同期します。対応するファイルを閉じる直前に呼び出す必要があります。

sync()は、変更されたすべてのファイルをディスクにコミットします。

0
user3428045