8

関数呼び出しfwrite()を使用して、Linux のパイプにデータを書き込みます。

以前は、fwrite()データの小さなチャンク (平均 20 バイト) に対して繰り返し呼び出されていたため、バッファリングは に任されていましたfwrite()。プロセスの strace は、一度に 4096 バイトのデータが書き込まれていることを示しました。

この書き込みプロセスが私のプログラムのボトルネックであることが判明しました。そこで、コード内のデータを 64KB のブロックにバッファリングしてから、一度に を使用してブロック全体を書き込むことにしましたfwrite()。以前setvbuf()は FILE* ポインターを「バッファリングなし」に設定していました。

パフォーマンスの向上は、私が期待したほど重要ではありませんでした。

さらに重要なことに、strace出力は、データがまだ一度に 4096 バイト書き込まれていることを示していました。誰かが私にこの振る舞いを説明してもらえますか? 64KB のデータで呼び出しfwrite()ている場合、一度に 4096 バイトしか書き込まれないのはなぜですか?

fwrite()FILE* ポインターを使用してパイプにデータを書き込むための代替手段はありますか?

4

2 に答える 2

8

4096 は、パイプラインの基礎となる Linux 機構に由来します。発生する場所は 2 か所あります。1 つはパイプラインの容量です。容量は、古いバージョンの Linux では 1 システム ページであり、32 ビット i386 マシンでは 4096 バイトです。(より新しいバージョンの Linux では、容量は 64K です。)

その 4096 バイトの問題に遭遇するもう 1 つの場所は、定義済みの定数PIPE_BUF(原子的に処理されることが保証されているバイト数) にあります。Linux では、これは 4096 バイトです。この制限が何を意味するかは、パイプラインをブロッキングまたは非ブロッキングのどちらに設定したかによって異なります。man -S7 pipeすべての悲惨な詳細については、 aを実行してください。

大量のデータを高速で交換しようとしている場合は、パイプの使用を再考することをお勧めします。Linuxボックスを使用しているため、共有メモリはオプションです。パイプを使用して、シグナリング メカニズムとして比較的少量のデータを送信できます。

于 2012-04-25T07:57:58.623 に答える
4

バッファリングの動作を変更したい場合は、 の直後fopen(または標準のファイルハンドルstdinstdout、の場合は I/O の前) に変更する必要がありますstderr。また、バッファリングを無効にしたり、自分でバッファを管理したりしたくありません。setvbufむしろ、適切に使用できるように64K バッファを指定してください。

バッファリングを手動で管理したい場合は、使用しないでくださいstdio。下位レベルopenの 、write、およびclose呼び出しを使用します。

于 2012-04-25T07:33:19.323 に答える