我不明白fork()的这个例子

时间:2012-02-12 22:34:03

标签: c unix fork

我有这个代码示例,但我不明白为什么这个代码会创建5个进程加上原始代码。 (共6个过程)

#include <unistd.h>

int main(void) {
    int i;
    for (i = 0; i < 3; i++) {
        if (fork() && (i == 1)) {
            break;
        }
    }
}

Process graph

7 个答案:

答案 0 :(得分:30)

fork()将进程分成两部分,并返回0(如果此进程是子进程),或者返回子进程的PID(如果此进程是父进程)。所以,这一行:

if (fork() && (i == 1)) break;

说“如果这是父进程,这是第二次通过循环,突破循环”。这意味着循环运行如下:

  • i == 0:第一次循环,i为0,我们创建两个进程,都进入i == 1的循环。 现在共有两个流程

  • i == 1:这两个进程都是fork,但是由于if (fork() && (i == 1)) break;行,其中两个进程没有继续迭代(两个不继续的进程都是父进程fork调用)。 现在共有四个流程,但其中只有两个流程继续循环。

  • i == 2:现在,继续循环的两个分叉,导致6个进程。

  • i == 3:所有6个进程都退出循环(从i < 3 == false开始,不再有循环)

答案 1 :(得分:12)

如果你的主进程有pid A,而B-F是subprocesses pids,那么:

A    spawns  B          i=0
A    spawns  C          i=1
C    run from 'fork'    i=1
C    spawns  D          i=2
B    run from 'fork'    i=0
B    spawns  E          i=1
D    run from 'fork'    i=2
E    run from 'fork'    i=1
E    spawns  F          i=2
F    run from 'fork'    i=2

其中i是(子)进程'上下文的i的值。 由于fork会创建正在运行的流程的精确副本,因此也会复制变量i。当A生成B时,i为0.当A生成C时,i为1。由于i == 1,进程A现在退出for循环。

现在,子进程C开始运行,i == 1.请注意,它不会在for循环内部中断,因为在C的产生点,fork()返回0.相反它将循环,将i增加到2,生成D,并因for循环条件而退出。

子进程B启动时有i == 0。它产生子进程E,并在for循环内部中断。 (i == 1)

等等......

当你想找出这些东西时,我可以给你一个建议:

制作中间变量并打印出来。

我修改了你的代码,以便打印出我刚才描述的内容:

#include <unistd.h>
#include <stdio.h>

int main(void) {
    int i;
    for (i= 0; i < 3; ++i) {
        int f = fork();
        printf("%i\tspawns\t%i\ti=%i\n", getpid(), f, i);
        if (f && (i == 1))
            break;
    }

    getchar();
}

答案 2 :(得分:6)

在父进程中,fork()返回子进程的PID,并在子进程中返回0.考虑到这一点,请查看for循环的每次迭代: (为简单起见,我们假设原始过程的PID为1)

  1. i == 0
    • 过程1:i == 0,fork返回子进程的PID(比如2)(2!= 0),true&amp;&amp; false == false,所以我们不会破坏。
    • 过程2:i = 0,fork返回0,false&amp;&amp; false == false,所以我们不会破坏。
  2. i == 1
    • 过程1:i == 1,fork返回子进程的PID(比如3),true&amp;&amp; true == true,所以休息。
    • 过程2:i == 1,fork返回子进程的PID(比如4),true&amp;&amp; true == true,所以休息。
    • 过程3:i == 1,fork返回0,false&amp;&amp; true == false,所以不要破坏。
    • 过程4:i == 1,fork返回0,false&amp;&amp; true == false,所以不要破坏。
  3. i == 2
    • 流程1不在循环中。
    • 流程2不在循环中。
    • 过程3:i == 2,fork返回子进程的PID(比如5),true&amp;&amp; false == false,所以不要破坏
    • 过程4:i == 2,fork返回子进程的PID(比如6),true&amp;&amp; false == false,所以不要破坏
    • 过程5:i == 2,fork返回0,false&amp;&amp; false == false,所以不要破坏
    • 过程6:i == 2,fork返回0,false&amp;&amp; false == false,所以不要破坏
  4. i == 3所以完成循环。

答案 3 :(得分:5)

我可以在这里计算六个进程(X):

i=0          fork()
            /      \
i=1   fork()        fork()
      /    \>0       /   \>0
      |    X break   |   X break
i=2 fork()       fork()
     / \          /  \
    X  X         X    X

答案 4 :(得分:3)

循环从i==0运行到i==2

在第一次迭代中,原始过程(p0)创建另一个(p1)

在第二次迭代中,p0p1分别创建一个新进程(p2和p3),并中断(自i==1fork返回非零给父亲的价值。)

在第三次迭代中,p2p3分别创建一个新进程(p4和p5)。

所以,最后,你有5个新流程。

答案 5 :(得分:3)

首先我们有一个过程。考虑循环的迭代:

i = 0

第一个进程调用fork。现在我们有2个流程。

i = 1

这两个进程调用fork。现在我们有4个。

Fork在新创建的进程中返回0:两个进程将从循环中断开,两个进程将在循环中继续。

i = 2

剩下的两个进程调用fork。我们获得了2个新流程(共6个)。

答案 6 :(得分:2)

在子进程中,循环继续迭代。所以他们也制作了新的流程。