デフォルトでは、プログラムの I/O はバッファリングされていることを知りました。つまり、一時ストレージから要求元のプログラムに提供されます。バッファリングによって IO パフォーマンスが向上することは理解しています (おそらくシステム コールの削減による)。Cのように、バッファリングを無効にする例を見てきsetvbuf
ました。2 つのモードの違いは何ですか?
2 に答える
続行する前に出力が書き込まれたことを確認したいときはいつでも、バッファリングされていない出力が必要です。1 つの例は、C ランタイム ライブラリでの標準エラーです。これは通常、デフォルトではバッファリングされません。エラーは (願わくば) めったに発生しないため、エラーについてすぐに知りたいと思うでしょう。一方、標準出力は、はるかに多くのデータが通過すると想定されているため、単純にバッファリングされます。
もう 1 つの例は、ロギング ライブラリです。ログ メッセージがプロセスのバッファ内に保持されていて、プロセスがコア ダンプする場合、出力が書き込まれない可能性が非常に高くなります。
さらに、最小化されるのはシステム コールだけではなく、ディスク I/O も同様です。プログラムが一度に 1 バイトずつファイルを読み取るとします。バッファリングされていない入力では、おそらくブロック全体を読み込む必要があるにもかかわらず、バイトごとに (比較的非常に遅い) ディスクにアクセスします (ディスク ハードウェア自体にバッファがある場合がありますが、それでもディスク コントローラにアクセスします)。インメモリ アクセスよりも遅くなります)。
バッファリングにより、ブロック全体が一度にバッファに読み込まれ、個々のバイトが (インメモリで信じられないほど高速な) バッファ領域から配信されます。
次の例のように、バッファリングにはさまざまな形式があることに注意してください。
+-------------------+-------------------+
| Process A | Process B |
+-------------------+-------------------+
| C runtime library | C runtime library | C RTL buffers
+-------------------+-------------------+
| OS caches | Operating system buffers
+---------------------------------------+
| Disk controller hardware cache | Disk hardware buffers
+---------------------------------------+
| Disk |
+---------------------------------------+
ディスクに書き込む準備ができている大量のバイト シーケンスが既にあり、中間の 2 番目のバッファーへの余分なコピーを避けたい場合は、バッファーなしの出力が必要です。
バッファリングされた出力ストリームは、書き込み結果を中間バッファに蓄積し、十分なデータが蓄積された (またはflush()
要求された) 場合にのみ、OS ファイル システムに送信します。これにより、ファイル システム呼び出しの数が減少します。ほとんどのプラットフォームでファイル システム呼び出しは ( short と比較してmemcpy
) コストがかかる可能性があるため、多数の小さな書き込みを実行する場合は、バッファリングされた出力が最終的に有利です。送信するバッファがすでに大きい場合は、通常、バッファなしの出力の方が適しています。中間バッファにコピーしても、OS 呼び出しの数はさらに減らず、追加の作業が発生します。
バッファリングされていない出力は、データが確実にディスクに到達することとは関係ありません。この機能は によって提供されflush()
、バッファリングされたストリームとバッファリングされていないストリームの両方で機能します。バッファリングされていない IO 書き込みは、データが物理ディスクに到達したことを保証するものではありません。OS ファイル システムは、データのコピーを無期限に保持することができ、必要に応じてディスクに書き込むことはありません。を呼び出すときにディスクにコミットする必要があるだけですflush()
。(があなたに代わってclose()
電話することに注意してください)。flush()