whileループをバッシングしてパイプから読み込みます。

whileループをバッシングしてパイプから読み込みます。

Bashスクリプトのワインを介してUbuntuで実行されているWindowsコマンドラインプログラムがあります。 Bashスクリプトは基本的に次のようになります。

wine myprogram.exe | while read line
do
   # Process line
done

私はmyprogram.exeを書いたので、できるだけ早くデータをエクスポートすることがわかりました。私のプログラムがwhileループが処理できるよりも速くデータを吐き出す場合、Bash whileループがデータを処理する方法を説明できる人はいますか?カーネルスケジューラがあまりにも多くのデータを生成する場合、myprogram.exeをスリープモードに切り替える隠し魔法はありますか?誰でも?現在私はそれが黒魔法になる方に傾いている。

答え1

まず、プログラムは独自の出力バッファリングを実行できます。これは時々」標準入出力Cでこれを行うライブラリコンポーネント名の後に「バッファリング」を追加します。などで宣言されputcた関数fputsです。その場合、通常は数キロバイトの出力バーストを生成します(デフォルトは、出力が端末に渡されるときにすべての改行でバッファをフラッシュすることです)。fprintfstdio.h

ある時点で、プログラマーまたは基本ライブラリー関数が呼び出されます。write明らかに。これは、指定されたデータをパイプに書き込むようにカーネルに要求します。カーネルは、データの全部または一部を書き込みとして決定できます。ファイルはパイプなので、カーネルはデータをパイプのバッファにコピーします。パイプバッファがいっぱいになると、writeスペースが利用可能になるまでシステムコールがブロックされます。つまり、プログラム(より正確にはwriteカーネルレベルのスレッドが複数ある場合は呼び出しスレッド)は、呼び出しがwrite返されるまで実行を再開しません。

(この場合、プログラムがパイプのファイル記述子を次のように設定した可能性がありますが、可能性は低いです。非遮断。この場合、カーネルがデータをコピーできないと判断した場合、システムwriteコールは0を返します。このような非ブロックシステムコールを実行するプログラムは、通常、以下を呼び出します。selectまたはpollepoll通信するファイル記述子の 1 つが入力または出力の準備ができるまでループをブロックします。 )

システムコール中にプログラムがブロックされるという事実は、スケジューリングアルゴリズムの選択とは関係がない。その核心は何でもスケジューラ区別する準備するスレッドにCPU時間を与えることができ、待つスレッドですができません。スケジューラの要点は、準備されたスレッドを選択し、そのスレッドがシステムコールを実行するか(スレッドを待機状態にする)、一部の非同期イベントが発生するまで(実際にプロセッサが実行されるようにすることです)邪魔する)。システムコールの処理中に、以前にブロックされたスレッドが準備されている可能性があります。たとえば、そのスレッドが呼び出しを行っていて、writeカーネルがその呼び出しからデータを転送できるようになったためです。準備されたスレッドを外部からブロックできるものがあります。一時停止信号(SIGSTOP。スケジューラは一種です準備チェックリスト次にスケジュールするスレッドの決定:準備されたスレッドのリスト(実際のスケジューラの簡単なリストよりもはるかに複雑な場合が多い)。

答え2

パイプラインと呼ばれます。これを実行するman 7 pipeと、パイプラインがどのように機能するかを確認できます。

以下を追加するように編集されました。 つまり、wineコマンドの出力はバッファに収集されます。バッファがいっぱいになり、ワインがより多くを書き込もうとすると、ワインプロセスはカーネルによって停止されます。バッファーのスペースが使用可能になると (つまり、while ループがバッファーから読み取られる場合)、停止したプロセスは再びアクティブになり、続行されます。これは古典的な制限されたバッファアルゴリズムですが、Unix / Linuxの世界ではパイプと呼ばれることがよくあります。これは非常に人気があり強力なので、これについてすべて学ぶことをお勧めします。

答え3

いいえ、闇の魔法はありません(少なくとも今回はありません)。ただ出力ストリームのキャッシュとバッファを使用します。

関連情報