理解for循环中的fork()

时间:2014-02-15 21:21:40

标签: c unix loops for-loop fork

我对理解fork()有疑问。任何人都可以解释一下,这个节目会打印什么?因为我准备考试,这是典型的问题。正是在这种情况下:

#include <stdio.h>

int main(int argc, char **argv) {
    int i;
    for(i = fork(); i < fork(); i++)
        execlp(“echo”, “sono”, argv[0], 0);
    system(“echo i+$i”);
}

对我而言,这条线

是不可理解的
for(i = fork(); i < fork(); i++)

这是什么意思?感谢所有提前。

2 个答案:

答案 0 :(得分:5)

通过完成第一个循环上下文的所有进程初始化第一个完整迭代,将发生以下情况:

<强> 1。初始化

i已从i = fork();

初始化
  • 处理父级i = pid(child1)
  • 子进程 child1 i = 0

在每个过程中点击条件测试会发生一些有趣的事情

<强> 2。流程:父母

i < fork()将分叉另一个子进程 child2 。如果返回的pid(child2)大于pid(child1),则满足条件测试并且父进程继续循环体

第3。流程:child1

  • i从初始化程序

  • 为零
  • i < fork()将分叉子进程 child3 。如果返回的pid(child3)大于i的值(它始终为零),则满足条件测试,并且child1进程继续循环体

    < / LI>

<强> 4。流程:child2

  • 从父级继承i,其中ipid(child1)
  • 此过程是在评估i < fork()时产生的,因此fork()将评估为0.因此......
  • i < fork()将评估为child1(pid) < 0,这将永远不会成真。条件测试失败,for循环终止。

<强> 5。流程:child3

  • 从其父级child1继承i = 0
  • 此过程是在评估i < fork()时产生的,因此fork()将评估为0.因此......
  • i < fork()将评估为0 < 0,这将永远不会成真。条件测试失败,for循环终止。

此时,parent和child1是进入循环体的唯一两个进程。另外两个(child2和child3)都没有通过条件检查。结果,发生了以下情况:

<强> 6。最后的步骤

  • 父进程已替换并使用execlp("echo", "sono", argv[0], 0);
  • 使用execlp("echo", "sono", argv[0], 0);
  • 替换
  • child2进程调用system("echo i+$i");终止
  • child3流程调用system("echo i+$i");终止

这很重要: 任何上述进程的任何都不会多​​次评估for-conditional。成功进行条件测试的任何内容都将替换为execlp()进程启动。任何未通过条件测试的东西都将离开循环并在system()调用后终止。因此,一旦任何进程超过条件(通过成功或失败),它将永远不会fork()另一个进程。

换句话说,这不是fork()炸弹。如果循环体或通过循环的后缀代码分叉了进程的另一个实例,它很容易成为fork()炸弹,但都不是


注意:可能 pid-rollover,其中进程ID重置并开始“填充漏洞”,导致第一个初始fork引入一个 less的child2 pid 比child1 pid。如果发生这种情况,(但不太可能),结果只会改为:

  • 父进程调用system(“echo i+$i”);并终止。
  • child1进程已替换为execlp("echo", "sono", argv[0], 0);
  • child2进程调用system("echo i+$i");并终止。
  • child3进程调用system("echo i+$i");并终止。

不是很血腥,但是后来也没有赢得彩票,人们认为它会一直发生在他们身上。

答案 1 :(得分:3)

代码令人难以置信的扭曲和错误。 但是当你不知道代码的作用时,只需“手动”运行它

int main(int argc, char **argv) {
    int i;
    for(i = fork(); i < fork(); i++)
        execlp(“echo”, “sono”, argv[0], 0);
    system(“echo i+$i”);
}

父进程:

i = fork();

此处i包含新创建的流程的PID

execlp(“echo”, “sono”, argv[0], 0);
<@> @Whozcraig在评论中纠正了我(并且因为犯了第一年的错误而感到羞耻)

它在输出上运行echo并输出"sono a.out"(考虑到prog的名称是a.out)。 execlp()用其参数替换当前进程并在此处停止执行。

在编辑之前

我说它是fork()无限期

子进程:

i = fork();

此处i包含值0,表示这是新创建的进程。

execlp(“echo”, “sono”, argv[0], 0);

再次出局......用其参数替换当前进程,并在echo结束后停止执行。

*在编辑之前,我说它再次fork()

所以一开始看看起来你有一个扭曲和疯狂的叉炸弹,它会成倍增长。但最后,你有一个扭曲而疯狂的单叉只能执行两次execlp()内容。

N.B。:system(“echo i+$i”);是无意义的,因为$i在此代码的上下文中没有任何意义。即使它永远不会被执行。

最后你的导师真的有悖常理。