ターミナルでいくつかのコマンドを実行していましたが、パイプコマンドを実行するときにUnix / Linuxがショートカットを取得しますか?
たとえば、100万行のファイルがあり、最初の10行にが含まれてhello world
いるとします。コマンドを実行するとgrep "hello world" file | head
、最初のコマンドが10行を検出するとすぐに停止しますか、それともファイル全体を最初に検索し続けますか?
ターミナルでいくつかのコマンドを実行していましたが、パイプコマンドを実行するときにUnix / Linuxがショートカットを取得しますか?
たとえば、100万行のファイルがあり、最初の10行にが含まれてhello world
いるとします。コマンドを実行するとgrep "hello world" file | head
、最初のコマンドが10行を検出するとすぐに停止しますか、それともファイル全体を最初に検索し続けますか?
回答:
並べ替え。シェルは、実行中のコマンドが何をするのか分からず、一方の出力を他方の入力に接続するだけです。
grep
「hello world」と言う10行を超える行が見つかった場合は、必要な10行head
すべてを取得し、パイプを閉じます。これはgrep
SIGPIPEで強制終了されるため、非常に大きなファイルをスキャンし続ける必要はありません。
grep
/dev/null
プログラムがパイプに書き込もうとして、そのパイプから読み取るプロセスがない場合、ライタープログラムはSIGPIPEシグナルを受け取ります。プログラムがSIGPIPEを受け取ったときのデフォルトのアクションは、プログラムを終了することです。プログラムはSIGPIPEシグナルを無視することを選択できます。この場合、書き込みはエラー(EPIPE
)を返します。
あなたの例では、ここで何が起こるかのタイムラインです:
grep
そしてhead
コマンドは、並行して起動します。grep
入力を読み取り、処理を開始します。grep
出力の最初のチャンクを生成します。head
その最初のチャンクを読み取り、書き出します。grep
最初に終了する可能性があります)、最終的head
には希望の行数が出力されます。この時点でhead
終了します。grep
とhead
プロセスの相対的な速度に応じて、grep
一部のデータが蓄積され、まだ印刷されていない可能性があります。head
終了時に、grep
入力を読み込んでいるか内部処理を実行している可能性があります。その場合、引き続き実行します。grep
に、処理されたデータが書き出されます。その時点で、SIGPIPEを受け取り、死にます。grep
厳密に必要な入力よりも少し多くの入力を処理する可能性がありますが、通常は数キロバイトのみです。
head
通常、数キロバイトのチャンクで読み取ります(read
各バイトに対してシステムコールを発行するよりも効率的です。この動作はバッファリングと呼ばれます)。したがって、目的の最終行の後の最後のチャンクの残りは破棄されます。grep
出力チャンクになる準備ができているいくつかのデータを蓄積した可能性があります(再度バッファリング)。出力バッファをフラッシュしようとすると、SIGPIPEを受け取ります。すべてのシステムのすべては、フィルタリングユーティリティが自然に効率的に動作するように正確に設計されています。出力チャネルが停止したときに継続する必要があるプログラムは、SIGPIPEシグナルを無視するステップを実行する必要があります。
Sortof、パイプラインは次のように機能します。最初のコマンドを実行し、次に2番目のコマンドを実行します。
つまり、A|B
与えられたコマンドにしましょう。そして、かどうかは不明であるA
か、B
最初に起動します。複数のCPUがある場合、それらはまったく同時に開始する場合があります。パイプは、未定義だが有限量のデータを保持できます。
Bがパイプから読み取ろうとしたが、データが利用できない場合B
、データが到着するまで待機します。B
ディスクから読み取っていた場合B
、同じ問題が発生している可能性があり、ディスクの読み取りが完了するまで待つ必要があります。より近い例えは、キーボードからの読み取りです。そこで、B
ユーザーが入力するのを待つ必要があります。しかし、これらすべてのケースで、Bは「読み取り」操作を開始し、完了するまで待つ必要があります。しかしif B
がsの部分的な出力のみを必要とするようなコマンドである場合、入力レベルに到達しA
た特定のポイントはSIGPIPEによって強制終了されます。B
A
場合A
試みは、パイプへの書き込みをし、パイプがいっぱいになる、A
自由になるためにパイプでいくつかの部屋を待つ必要があります。A
端末に書き込んでいた場合、同じ問題が発生する可能性があります。端末にはフロー制御があり、データのペースを調整できます。いずれにしても、to A
は、「書き込み」操作を開始し、書き込み操作が完了するまで待機します。
A
そしてB
全ての共処理はパイプに連通するが、共同プロセスとして動作しています。どちらも他方を完全に制御することはできません。
head
終了)、プログラムでSIGPIPEシグナルが発生し、デフォルトの動作は終了します。
grep
パイプを直接制御することはなく(データを受信するだけです)、パイプを直接制御grep
することはありません(データを送信するだけです)...
どのようなgrep
他のプログラムがない、または、完全にアップしているプログラムの内部ロジックにあります。あなたが教えてくれた場合はgrep
早期に行うために、コマンドラインオプションを経由していたときに出口を-、それは、それ以外の場合は、パターンを探して、ファイルの最後までの一気飲みますでしょう...
同様に、ターミナルはの内部動作grep
とshell
のパイピングアクションから完全に切り離されています...ターミナルは基本的には起動パッドと出力ディスプレイにすぎません
-m
引数があります。