web-dev-qa-db-ja.com

既知のPIDですでに実行されているプロセスのパイプ/ printfバッファーを外部でフラッシュします

私はデータロギングアプリを書いています、すべてのプログラムは次のように開始されます:

_./program > out.bin
_

データコレクターは定期的にstdout出力ファイルをプールし、データを読み取ります。

問題は、IOストリームがバッファリングされ、一部のプログラムが1バイト/秒のようにデータを出力する場合、データが実際に出力されるまでに多くの時間がかかることです(デフォルトの4kBバッファサイズでは最大4k秒)。洗い流された。

私の質問は、stdout/pipe/printfバッファを強制的に外部でフラッシュする方法、つまりfflush(stdout)のような外部で呼び出す方法です。

パイプ内のバッファリングをオフにする のようなさまざまなサイトを読んだことがありますが、IOのパフォーマンスに大きな影響があるため、バッファを無効にすることはできません(測定)。

私は生産のための高性能ソリューションを探しています、そしてこれらの以下の条件は常に満たされます:

  • プログラム(データプロデューサー)のPIDは常にわかっています
  • 出力は常に既知のパスを持つファイルです
  • データロギングプロセスにはフルルートアクセスがあります
2
mvorisek

実行中のプログラムのソースにアクセスできますか?

任意の実行可能ファイルのフラッシュを強制することは、理論的には不可能ではありませんが、非常に困難です。コード内でfflush関数とstdout引数を見つけて、プログラムの実行を中断し、fflushの呼び出しを手配してから、実行を続行する必要があります。プログラムが共有ライブラリを使用している場合は、少なくとも最初の部分が簡単になり、fflushstdoutが見つかりますが、それでも呼び出しをシミュレートする必要があります。また、不明なバイナリの場合、stdioを使用したのか、独自のバッファリングメカニズムを実装したのかを知ることはできません。出力ファイルのパスを知っていることは役に立ちません。

gdbを使用してから、attachコマンドを使用してプロセスにアタッチできます。たぶん、gdbfflush関数を呼び出すことができます。

プログラムのソースがある場合は、バッファーをフラッシュするシグナルハンドラーを実装し、バッファーをフラッシュするときにシグナルを送信するだけです。

パイプを試すことができます。出力がパイプの場合、プログラムはバッファリングしない可能性があります。に変更します

./program | your_program > out.bin

プログラムは入力を受け入れ、それをバッファリングし、信号を受信するとバッファをフラッシュできます。それでもCPUオーバーヘッドは追加されますが、ディスクオーバーヘッドは追加されません。

3
RalfFriedl
gdb -p PID -batch -ex 'p fflush(stdout)'

他のデバッグやハッキングと同様に、YMMV。

2
mosvy