私はこれをファイルオブジェクトの Python ドキュメントで見つけました:
flush()は、必ずしもファイルのデータをディスクに書き込むとは限りません。この動作を保証するには、flush()に続けてos.fsync()を使用します。
だから私の質問は:Pythonは正確には何をしflush
ているのですか?ディスクへのデータの書き込みが強制されると思いましたが、今はそうではないことがわかりました。どうして?
私はこれをファイルオブジェクトの Python ドキュメントで見つけました:
flush()は、必ずしもファイルのデータをディスクに書き込むとは限りません。この動作を保証するには、flush()に続けてos.fsync()を使用します。
だから私の質問は:Pythonは正確には何をしflush
ているのですか?ディスクへのデータの書き込みが強制されると思いましたが、今はそうではないことがわかりました。どうして?
回答:
通常、2つのレベルのバッファリングが含まれます。
内部バッファは、プログラミング対象のランタイム/ライブラリ/言語によって作成されたバッファであり、すべての書き込みに対するシステムコールを回避することで、処理を高速化することを目的としています。代わりに、ファイルオブジェクトに書き込むときは、そのバッファーに書き込みます。バッファーがいっぱいになると、データはシステムコールを使用して実際のファイルに書き込まれます。
ただし、オペレーティングシステムのバッファが原因で、これはデータがディスクに書き込まれることを意味しない場合があります。これは、ランタイムによって維持されているバッファからオペレーティングシステムによって維持されているバッファにデータがコピーされることを意味するだけかもしれません。
何かを書き込んで、それがバッファ(のみ)に到達し、マシンの電源が切れた場合、マシンの電源を切ると、そのデータはディスク上にありません。
だから、助けるためにあなたが持っているとflush
し、fsync
に、それぞれのオブジェクトにメソッドがあります。
1つ目flush
は、プログラムバッファーに残っているデータを実際のファイルに書き込むだけです。通常、これはデータがプログラムバッファーからオペレーティングシステムバッファーにコピーされることを意味します。
具体的には、これは、別のプロセスが同じファイルを読み取り用に開いている場合、そのファイルにフラッシュしたばかりのデータにアクセスできることを意味します。ただし、必ずしも「永続的に」ディスクに保存されているという意味ではありません。
これを行うには、os.fsync
すべてのオペレーティングシステムバッファーが対象のストレージデバイスと同期していることを確認するメソッドを呼び出す必要があります。つまり、このメソッドは、オペレーティングシステムバッファーからディスクにデータをコピーします。
通常、どちらの方法でも気にする必要はありませんが、実際にディスク上で何が発生するかについての妄想が良い状況にある場合は、指示どおりに両方の呼び出しを行う必要があります。
2018年の補遺。
キャッシュメカニズムを備えたディスクが2013年よりもはるかに一般的になったため、今ではさらに多くのレベルのキャッシュとバッファーが含まれていることに注意してください。私は仮定し、これらのバッファが同様に同期/フラッシュの呼び出しによって処理されますが、私は本当に知りません。
fsync
原子性のために必要です。ファイルを閉じてから再度開いてfsync
、途中にa がないコンテンツを見つけることはできません。これはしばしば機能しますが、例えばext4とデフォルトのマウントオプションを備えたLinuxでは機能しません。また、fsync
ハードディスクの内部バッファリングがフラッシュに指示されない場合があります。FSYNCが(ラップトップモードで)無効にすることができ、そして2:本当にマグネットフリップ1ので、プラッタ上の鉄を保証するものではありません。
オペレーティングシステムがそうしない可能性があるためです。フラッシュ操作により、ファイルデータがRAMのファイルキャッシュに強制的に送られ、そこから実際にディスクに送信するのはOSの仕事です。
actually
ここでは相対的です。ターゲットデバイスで書き込みキャッシュが有効になっている場合、データがos.fsync()
戻ったときに実際のプラッター/チップにデータが到達していない可能性があります。
内部バッファをフラッシュします。これにより、OSがバッファをファイルに書き込みます。[1] Pythonは、特に構成しない限り、OSのデフォルトのバッファリングを使用します。
ただし、OSがまだ協力しないことを選択する場合もあります。特に、Windows / NTFSでの書き込み遅延などの素晴らしい機能を備えています。基本的に、内部バッファはフラッシュされますが、OSバッファはまだそれを保持しています。したがってos.fsync()
、それらの場合には、ディスクに書き込むようにOSに指示する必要があります。
with file('blah') as fd: #dostuff
構造体を使用すると、ファイル記述子を確実に閉じることがわかります。また、フラッシュまたは同期しますか?