フォーク爆弾のフォーク()はどこにありますか:(){ :|: & };:?

フォーク爆弾のフォーク()はどこにありますか:(){ :|: & };:?

警告:ほとんどのシェルでこのコマンドを実行すると、システムが破損し、回復に強制シャットダウンが必要です。

私は再帰関数:(){ :|: & };:とその機能を理解しています。しかし、フォークシステムコールがどこにあるのかわかりません。確かではありませんが、パイプの中にあるようです|

答え1

のパイプによって、x | yパイプをフォアグラウンドプロセスグループの一部として含むサブシェルが作成されます。これにより、サブシェル(パス)が引き続き生成され、fork()フォーク爆弾が生成されます。

$ for (( i=0; i<3; i++ )); do
>     echo "$BASHPID"
> done
16907
16907
16907
$ for (( i=0; i<3; i++ )); do
>     echo "$BASHPID" | cat
> done
17195
17197
17199

:ただし、ブランチはコードの最後の呼び出しであるコードが実行されるまで実際には発生しません。

フォーク爆弾の解体の仕組み:

  • :()- という新しい関数を定義します。:
  • { :|: & }- 呼び出し関数をバックグラウンド呼び出し関数の別のインスタンスに再帰的に転送する関数の定義
  • :- フォーク爆弾機能を呼び出す

これは多くのメモリを占有しない傾向があるが、PIDを占有し、CPUサイクルを消費する。

答え2

コードの最後のビット;:は関数を実行することです:(){ ... }。ここでフォークが発生します。

セミコロンは最初のコマンドを終了し、関数を呼び出す別のコマンドを開始します:。関数定義には:独自の呼び出し()が含まれ、その呼び出しの出力はバックグラウンドバージョンにパイプされます:。これはプロセスを無期限にサポートします。

この関数を呼び出すたびに:()C関数を呼び出すことですfork()。結局、これはシステムのすべてのプロセスID(PID)を使い果たします。

はい

|:&何が起こっているのかを理解できるように、他のものに置き換えることができます。

オブザーバーの設定

ターミナルウィンドウで、次の操作を行います。

$ watch "ps -eaf|grep \"[s]leep 61\""

「ヒューズ遅延」フォーク爆弾設定

別のウィンドウでは、少し変更されたFork Bombバージョンを実行します。このバージョンは独自の制限を試して、そのバージョンが何をしているのかを調べることができます。私たちのバージョンは、この関数を呼び出す前に61秒間スリープモードに入ります:()

また、最初の呼び出しが行われた後にバックグラウンドに配置することもできます。Ctrl+zを入力してbg

$ :(){ sleep 61; : | : & };:

# control + z
[1]+  Stopped                 sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &

最初のウィンドウでコマンドを実行すると、次のようにjobsなります。

$ jobs
[1]-  Running                 sleep 61 &
[2]+  Running                 : | : &

数分後:

$ jobs
[1]-  Done                    sleep 61
[2]+  Done                    : | :

観察者に確認

一方、他のウィンドウでは以下を実行していますwatch

Every 2.0s: ps -eaf|grep "[s]leep 61"                                                                                                                                             Sat Aug 31 12:48:14 2013

saml      6112  6108  0 12:47 pts/2    00:00:00 sleep 61
saml      6115  6110  0 12:47 pts/2    00:00:00 sleep 61
saml      6116  6111  0 12:47 pts/2    00:00:00 sleep 61
saml      6117  6109  0 12:47 pts/2    00:00:00 sleep 61
saml      6119  6114  0 12:47 pts/2    00:00:00 sleep 61
saml      6120  6113  0 12:47 pts/2    00:00:00 sleep 61
saml      6122  6118  0 12:47 pts/2    00:00:00 sleep 61
saml      6123  6121  0 12:47 pts/2    00:00:00 sleep 61

プロセス層

a は、ps -auxf次のプロセス階層を示しています。

$ ps -auxf
saml      6245  0.0  0.0 115184  5316 pts/2    S    12:48   0:00 bash
saml      6247  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
....
....
saml      6250  0.0  0.0 115184  5328 pts/2    S    12:48   0:00 bash
saml      6268  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
saml      6251  0.0  0.0 115184  5320 pts/2    S    12:48   0:00 bash
saml      6272  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
saml      6252  0.0  0.0 115184  5324 pts/2    S    12:48   0:00 bash
saml      6269  0.0  0.0 100988   464 pts/2    S    12:48   0:00  \_ sleep 61
...
...

清掃時間

Aはkillall bash仕事が制御不可能になる前に仕事が起こるのを防ぎます。この方法で掃除するのは少し厳しいかもしれませんが、すべてのbash皮を剥がさない可能性があるより柔らかく穏やかな方法は、次のことです。

  1. フォーク爆弾が実行される疑似端末を決定します。

    $ tty
    /dev/pts/4
    
  2. 擬似端末の終了

    $ pkill -t pts/4
    

どうしたの?

との各呼び出しは、bashコマンドを実行するシェルから呼び出されるsleepC関数です。fork()bash

関連情報