パイピングでは、最初のインスタンスが他のインスタンスが開始する前に終了する必要はありません。実際には、最初のインスタンスのstdoutを2番目のインスタンスのstdinにリダイレクトするだけなので、同時に実行できます(フォーク爆弾が機能するために必要です)。
さて、出力は正確に何:
ですか?他に何が渡されてい:
ますか?
「:」は他の「:」インスタンスに何も書き込まず、単にstdoutを2番目のインスタンスのstdinにリダイレクトするだけです。実行中に何かを書いた場合(それ自体はフォークしないので何もしません)、それは STDIN他のインスタンスの。
stdinとstdoutを想像するのに役立ちますをパイルとして:
stdinに書き込まれたものはすべて、プログラムがそれから読み取ることを決定したときに、stdoutは同じように機能します:書き込むことができるパイルなので、他のプログラムは必要に応じて読み取ることができます。
そうすれば、通信が発生しないパイプ(2つの空のパイル)や非同期の書き込みと読み取りのような状況を想像するのは簡単です。
それは正確に2回実行されますか?私の意見では:
、最初のもの:
が実行を終了するまで何も渡されず、実際には終了しません。
インスタンスの入力と出力をリダイレクトしているだけなので、最初のインスタンスが終了してから2番目のインスタンスが開始する必要はありません。実際には、両方を同時に実行して、2番目のデータがその場で最初のデータによって解析されるデータを処理できるようにすることが実際に望まれます。これがここで発生することです。どちらも最初の呼び出しが完了するのを待たずに呼び出されます。これは、コマンドのすべてのパイプチェーン行に適用されます。
同じロジックが:(){:|:&} ;:にも当てはまると考えています
:(){ : & };:
と同じ仕事をする
:(){ :|: & };:
最初のものは、再帰的に実行されているにもかかわらず、関数がバックグラウンドで呼び出されているため、機能しません(: &
)。最初の:
子は、「子」:
が戻るまで待機せずに終了するため、最終的には:
実行中のインスタンスが1つだけになります。あなたが持っていた場合は:(){ : };:
最初にするので、それは、しかし働くだろう:
「子」を待つだろう:
、独自の「子」を待つことになる、戻って:
返すように、というように。
実行されるインスタンスの数に関して、さまざまなコマンドがどのように見えるかを以下に示します。
:(){ : & };:
1インスタンス(呼び出し:
と終了)-> 1インスタンス(呼び出し:
と終了)-> 1インスタンス(呼び出し:
と終了)-> 1インスタンス-> ...
:(){ :|: &};:
1インスタンス(2を呼び出して:
終了)-> 2インスタンス(各1が2を呼び出して:
終了)-> 4インスタンス(各1が2を呼び出して:
終了)-> 8インスタンス-> ...
:(){ : };:
1インスタンス(呼び出し:
て、戻るのを待つ)-> 2インスタンス(子が別の:
を呼び出して、戻るのを待つ)-> 3インスタンス(子が別の呼び出し:
をして、戻るのを待つ)-> 4インスタンス-> ...
:(){ :|: };:
1インスタンス(2を呼び出し:
、戻るのを待つ)-> 3インスタンス(子供が:
それぞれ2を呼び出し、戻るのを待つ)-> 7インスタンス(子供が2を呼び出す:
それぞれて戻るのを待つ) -> 15インスタンス-> ...
ご覧のとおり&
、呼び出された関数が戻る前に呼び出し先が終了するため、バックグラウンドで(を使用して)関数を呼び出すと、実際にはフォークボムが遅くなります。
:|:
。2番目のコマンドは:
、最初のコマンドが完了するのを待つ必要はありません。