我大致了解 this common version
:(){ :|:& };:
bash fork 炸弹的工作原理。
但是,我看过另一个版本(特别是 bash)
#!/bin/bash
$0 &
$0 &
在 Wikipedia fork bomb article 和 SO 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/