典型的炮弹“叉子炸弹”到底如何称呼自己两次?


15

询问了Askubuntu和许多其他Stack Exchange网站上著名的Fork Bomb问题之后,我不太明白每个人都在说什么,这很明显。

许多答案(最佳示例)都这样说:

{:|: &}表示运行功能:并将其输出:再次发送到功能”

好吧,确切的输出是:什么?传递给对方的是:什么?

并且:

本质上,您正在创建一个函数,该函数每次调用都会调用两次,并且无法终止自身。

两次执行的精确度如何?在我看来,:直到第一个:完成执行之前,任何内容都不会传递给第二个,实际上这将永远不会结束。

C例如,

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

第二个foo()根本不执行,只是因为第一个foo()永远不会结束。

我在想,同样的逻辑也适用于:(){ :|: & };:

:(){ : & };:

做与

:(){ :|: & };:

请帮助我理解逻辑。


9
管道中的命令在中并行运行:|:,第二个:不需要等待第一个完成。
cuonglm '16

Answers:


26

管道不需要第一个实例在另一个实例开始之前完成。实际上,实际上它所做的只是将第一个实例的stdout重定向到第二个实例的stdin,因此它们可以同时运行(因为它们必须使分叉炸弹正常工作)。

好吧,确切的输出是:什么?传递给对方的是:什么?

':'不会向另一个':'实例写入任何内容,它只是将标准输出重定向到第二个实例的标准输入如果它在执行过程中写了一些东西(它永远不会做,因为它除了分叉本身什么也不会做),它将转到另一个实例的标准输入

这有助于将stdinstdout想象成一堆:

当程序决定从标准输入中读取内容时,写入标准输入的内容都会准备就绪,而标准输出则以相同的方式工作:可以写入的内容,以便其他程序在需要时可以从中读取。

这样一来,就很容易想象出诸如管道之类的情况,其中没有发生通信(两个空堆)或非同步的读写操作。

两次执行的精确度如何?在我看来,:直到第一个:完成执行之前,任何内容都不会传递给第二个,实际上这将永远不会结束。

由于我们只是重定向实例的输入和输出,因此不需要第一个实例在第二个实例开始之前完成。实际上通常通常希望两者同时运行,以便第二个可以同时处理第一个正在解析的数据。这就是这里发生的情况,两者都将被调用,而无需等待第一个完成。这适用于所有管道链命令行。

我认为相同的逻辑适用于:(){:|:&} ;:和

:(){ : & };:

做与

:(){ :|: & };:

第一个不起作用,因为即使它以递归方式运行,该函数仍在后台(: &)中被调用。第一个:不等到“子” :返回才结束自身,因此最后您可能只有一个:运行实例。如果有的:(){ : };:话,它将起作用,因为第一个:将等待“子” :返回,然后将等待其自己的“子” :返回,依此类推。

就运行多少实例而言,以下是不同的命令:

:(){ : & };:

1个实例(调用:和退出)-> 1个实例(调用:和退出)-> 1个实例(调用:和退出)-> 1个实例-> ...

:(){ :|: &};:

1个实例(调用2 :并退出)-> 2个实例(每个调用2 :并退出)-> 4个实例(每个调用2 :并退出)-> 8个实例-> ...

:(){ : };:

1个实例(调用:并等待它返回)-> 2个实例(子调用另一个:并等待它返回)-> 3个实例(子调用另一个:并等待它返回)-> 4个实例-> ...

:(){ :|: };:

1个实例(调用2 :并等待它们返回)-> 3个实例(孩子分别调用2 :并等待它们返回)-> 7个实例(孩子分别调用2 :并等待它们返回) -> 15个实例-> ...

如您所见,在后台调用函数(使用&)实际上会减慢fork炸弹的速度,因为被调用方将在被调用函数返回之前退出。


题。会:(){ : & && : &}; :也作为一个叉炸弹?您还将以指数方式增加,实际上,您可以: &在其中放置多个,以更快地增加它。
JFA

@JFA`─> $:(){:&&&:&}; :`给出语法错误bash: syntax error near unexpected token &&' 。您可以这样做::(){ $(: &) && $(: &)}; :,但是,与管道不同,它不会并行运行。相当于:(){: & };:。想验证吗?试试这些time $( $(sleep 1 & ) && $(sleep 1 &) ),这time $(sleep 1 | sleep 1)
Severus Tux

确切地说,:(){ $(: &) && $(: &)};是在第一实例和第二实例的返回值中发出逻辑与运算的函数。问题是,由于逻辑AND仅在两个值都为true时才为true,因此为了提高效率,只会运行第一个实例。如果其返回值为1,则第二个实例将运行。如果您想让叉式炸弹变得更快,我想您可以将更多实例:(){ :|:|: &}; :
传送

附带说明,许多脚本在以下情况下使用AND的这种行为:假设您要在prog1返回true(在bash中为0)时运行prog2。无需执行if语句(if [ prog1 ]; then; prog2; fi),您只需编写(prog1 && prog2),并且prog2仅在prog1的返回值为true时才运行。
IanC

好的,这些都是要点。我曾经&&打电话给apt-get update && apt-get upgrade,并且&在行的结尾在后台运行,但这很重要,因为它们不能一起工作。分号也不适用于&符。
JFA
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.