我大致了解 this common version

:(){ :|:& };:

bash fork 炸弹的工作原理。

但是,我看过另一个版本(特别是 bash)
#!/bin/bash
$0 &
$0 &

Wikipedia fork bomb articleSO answer 到我上面提到的原始叉式炸弹问题的 closed duplicate 中。

我正在寻找有关叉式炸弹的第二个(可能不太常见)版本的工作原理的解释。我已经用我目前对它的作用的理解评论了下面的代码,但我真的不明白它是如何以其他版本的 bash fork 炸弹的方式实现无限递归的(可能是由于我对 bash 的理解不足进程和背景)。
#!/bin/bash    # Specifies the location of the executable
               # to use in executing this script.
$0 &           # Duplicates (executes a new instance
               # of) the current running process ('$0')
               # (which would be the invocation of bash used
               # to start running the script, right?)
               # and background it ('&').
$0 &           # Do the same as above, where $0 would be
               # equivalent to the initial call to bash
               # used to start the script, right? Or, would
               # it be the backgrounded call to bash from the
               # second line? I'm leaning towards the former.

编辑:我对脚本的修订理解(至少在我目前担心的抽象级别)以注释代码的形式显示在下面。我已经将我的原始评论代码留给 future 的观众,他们可能和我最初有同样的误解。假设脚本位于 bomb.sh 中。
#!/bin/bash    # Script will execute using /bin/bash executable.
$0 &           # The current process (P) will spawn a child process (C1)
               # by invoking the command that spawned P
               # (/bin/bash ./bomb.sh). This makes the script recursive.
               # & allows processes to run in the background
               # (allowing process death and avoiding a potential
               # process limit).
$0 &           # Process P spawns a second child process (C2), also
               # in the background, which gives us the exponential growth
               # (in base 2) that we want per level of recursion.

最佳答案

如果你把这个炸弹分解一点,它可能更有意义。将此更改为:

#!/bin/bash
$0

这个炸弹会一遍又一遍地生成一个新的 shell 脚本副本:
$ ps auxw | grep pts/2
sarnold   2410  0.0  0.1  24840  6340 pts/2    Ss   Nov17   0:01 bash
sarnold  17280  0.0  0.0  12296  1600 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
sarnold  17281  0.0  0.0  12296  1600 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
sarnold  17282  0.0  0.0  12296  1600 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
sarnold  17283  0.0  0.0  12296  1596 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
sarnold  17284  0.0  0.0  12296  1600 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
...
$ ps auxw | grep pts/2 | wc -l
2077

每一个旧的本质上都是“死的”——等待从被执行的 child 那里获得退出状态。当然,这种情况不会发生,直到其中一个已执行的子项最终由于进程限制而无法执行。 (顺便提醒我,在玩得更远之前,设置 nproc rlimit 可能是个好主意。)

所以这个进程树看起来像这样:
1
 2
  3
   4
    5
     6

如果您将 & 添加到命令的末尾,您将看到较旧的代码最终会被调度并死亡。但是,新进程的形成同样迅速,因此这会导致相当大的流失,并有助于减少在产生最大数量的进程时它刚刚结束的机会。这棵树看起来更像这样:
1
 2
  3

    5
     6

       8

添加第二行 $0 & 会使树看起来有点不同:
           1
        2     3
      4   5 6   7

除了它可能不会这么好 - 第二个过程可能会开始第三个,而不是第一个开始第三个。它可能看起来非常困惑。

总体而言,每个“层”都会使前一层的大小增加一倍,但 execve(2) 只能如此频繁地调用——诀窍在于,与简单的炸弹相比,这个炸弹可能会强制执行更多的进程上下文切换,以及所有这些 TLB刷新将显着影响系统的性能。因为在执行两个 child 后, parent 基本上会随机死亡,init(8) 将有更多的进程重新成为 parent 。所有这些都会增加发送到 init(8) 进行清理的信号数量,这将使管理员更难登录并解决问题。

关于bash - 这个其他版本的 bash fork 炸弹是如何工作的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8394435/

10-09 03:07