典型的なシェル「fork bomb」は、どのくらい正確に自分自身を2回呼び出しますか?


15

Askubuntuや他の多くのStack Exchangeサイトで有名なFork Bombの質問を読んだ後、誰もが言っていることは明らかだとはわかりません。

多くの答え(最良の例)はこう言います:

{:|: &}関数:を実行し、その出力を:再度関数に送信することを意味します」

さて、出力は正確:ですか?他に何が渡されてい:ますか?

そしてまた:

基本的には、呼び出しごとに自分自身を2回呼び出す関数を作成し、自分自身を終了する方法はありません。

それはどのくらい正確に2回実行されますか?私の意見では:、最初のもの:が実行を終了するまで何も渡されず、実際には終了しません。

ではC例えば、

foo()
{
    foo();
    foo(); // never executed 
}

foo()最初のものfoo()が終了しないという理由だけで、2番目のものはまったく実行されません。

同じ論理が当てはまると思います :(){ :|: & };:

:(){ : & };:

と同じ仕事をする

:(){ :|: & };:

ロジックを理解してください。


9
パイプラインのコマンドは、で並行して実行されます:|:。2番目のコマンドは:、最初のコマンドが完了するのを待つ必要はありません。
クオンルム

回答:


26

パイピングでは、最初のインスタンスが他のインスタンスが開始する前に終了する必要はありません。実際には、最初のインスタンスのstdoutを2番目のインスタンスのstdinにリダイレクトするだけなので、同時に実行できます(フォーク爆弾が機能するために必要です)。

さて、出力は正確に何:ですか?他に何が渡されてい:ますか?

「:」は他の「:」インスタンスに何も書き込まず、単にstdoutを2番目のインスタンスのstdinにリダイレクトするだけです。実行中に何かを書いた場合(それ自体はフォークしないので何もしません)、それは STDIN他のインスタンスの。

stdinstdoutを想像するのに役立ちますをパイルとして:

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インスタンス-> ...

ご覧のとおり&、呼び出された関数が戻る前に呼び出し先が終了するため、バックグラウンドで(を使用して)関数を呼び出すと、実際にはフォークボムが遅くなります。


質問。思い:(){ : & && : &}; :もフォーク爆弾として動作しますか?また、指数関数的に増加し、実際には、複数: &のを挿入してさらに速くすることができます。
JFA

@JFA `─> $:(){:&&&:&}; : `は構文エラーを返しますbash: syntax error near unexpected token &&' 。これを行うことができます::(){ $(: &) && $(: &)}; :、しかし、再び、パイプラインとは異なり、それは並列に実行されません。これはに相当し:(){: & };:ます。確認したいですか?これらtime $( $(sleep 1 & ) && $(sleep 1 &) )とこれを試してくださいtime $(sleep 1 | sleep 1)
セブルスタックス

まさに、 :(){ $(: &) && $(: &)};最初と2番目のインスタンスの戻り値で論理AND演算を発行している関数です。問題は、両方の値が真である場合にのみ論理ANDが真になるため、効率のために最初のインスタンスのみが実行されることです。戻り値が1の場合、2番目のインスタンスが実行されます。フォーク爆弾をさらに高速にしたい場合は、次のように、より多くのインスタンスをチェーンにパイプすることができると思います:(){ :|:|: &}; :
-IanC

補足として、多くのスクリプトは次の状況でANDのこの動作を使用します。prog1がtrue(bashで0)を返す場合、prog2を実行するとします。ifステートメントを実行する代わりに(if [ prog1 ]; then; prog2; fi)を)と書くprog1 && prog2だけで、prog1の戻り値がtrueの場合にのみprog2が実行されます。
IanC

OK、これらはすべて素晴らしい点です。私は&&を呼び出してapt-get update && apt-get upgrade&行の最後でバックグラウンドで実行しますが、それは彼らが一緒に動作しないという素晴らしい点です。セミコロンもアンパサンドでは機能しません。
JFA
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.