了解UNIX fork()如何影响父进程

时间:2018-10-02 16:50:20

标签: c unix fork

我有以下使用fork()函数创建子进程的程序

#include <stdio.h>
   int main (){
   printf("PID:%d\n",getpid());//print1:P1
   fork();
   fork();
   fork();
   printf ("Done"); //print2:P2
}

我试图了解上述程序如何将“完成”打印8次,因为输出结果是这样。

3 个答案:

答案 0 :(得分:3)

您应注意,每个后续派生将由之前创建的子代执行。因此,流程层次结构如下:

Parent
  -- Child 1                   (first fork executed by Parent)
     -- Grandchild 1           (second fork executed by Child 1)
        -- Grand-grandchild 1  (third fork executed by Grandchild 1)
     -- Grandchild 2           (third fork executed by Child 1)
  -- Child 2                   (second fork executed by Parent)
     -- Grandchild 3           (third fork executed by Child 2)
  -- Child 3                   (third fork executed by Parent)

每个这些都将调用printf ("Done");。总共8个。

答案 1 :(得分:1)

通过调用fork()来创建进程时

 fork();

fork()之后的任何语句,一旦由子进程执行,就由父进程执行,就可以了。在您的情况下,fork()被称为三次,因此它打印8次Done。看起来像

fork();
printf ("Done\n"); /* once printed by child process & once by parent process, so for one fork() call, it prints 2 times Done. For 3 fork call, 8 times */

fork()的手册页中

  

fork()通过复制 调用来创建新流程   过程。的          新过程(称为子过程)与          呼叫过程

答案 2 :(得分:0)

我将使其更加直观:

步骤1

// Program 1
#include <stdio.h>
   int main (){
   printf("PID:%d\n",getpid());//print1:P1
   fork(); // <- Current Line
   fork();
   fork();
   printf ("Done"); //print2:P2
}

步骤2

执行此行时,它将分为两个程序:

// Program 1                                                   >----|
#include <stdio.h>                                                  |
   int main (){                                                     |
   printf("PID:%d\n",getpid());//print1:P1                          |
   fork(); // Returns child's PID [Program 1 Version 2]             |
   fork(); // <- Current line                                       |
   fork();                                                          |
   printf ("Done"); //print2:P2                                     |
}                                                                   |
                                                                    |
// Program 1 Version 2 (Child of Program 1)   >----|                |
#include <stdio.h>                                 |                |
   int main (){                                    |                |
   printf("PID:%d\n",getpid());//print1:P1         |                |
   fork(); // Returns 0, since it's a child        |                |
   fork(); // <- Current line                      |                |
   fork();                                         |                |
   printf ("Done"); //print2:P2                    |                |
}                                                  |                |

步骤3

程序1版本2执行其当前行时,它会创建

// Program 1 Version 2                       <-----|                |
#include <stdio.h>                                 |                |
   int main (){                                    |                |
   printf("PID:%d\n",getpid());//print1:P1         |                |
   fork();                                         |                |
   fork(); // Returns child's PID [Program 1 Version 2] Version 2   |
   fork(); // <- Current line                      |                |
   printf ("Done"); //print2:P2                    |                |
}                                                  |                |
                                              v----|                |
// [Program 1 Version 2] Version 2 (Child of Program 1 Version 2)   |
#include <stdio.h>                                                  |
   int main (){                                                     |
   printf("PID:%d\n",getpid());//print1:P1                          |
   fork();                                                          |
   fork(); // Returns 0 (It's a new child)                          |
   fork(); // <- Current line                                       |
   printf ("Done"); //print2:P2                                     |
}                                                                   |

程序1执行其当前行时,它会创建

// Program 1                                           <------------|
#include <stdio.h>                                                  |
   int main (){                                                     |
   printf("PID:%d\n",getpid());//print1:P1                          |
   fork();                                                          |
   fork(); // Returns child's PID [Program 1 Version 3]             |
   fork(); // <- Current line                                       |
   printf ("Done"); //print2:P2                                     |
}                                                                   |
                                                                    |
// Program 1 Version 3 (Child of Program 1)             <-----------|
#include <stdio.h>
   int main (){
   printf("PID:%d\n",getpid());//print1:P1
   fork();
   fork(); // Returns 0 (Is a new child)
   fork(); // <- Current line
   printf ("Done"); //print2:P2
}

步骤4

最后一个分支中的每个都再次复制每个程序,使您有8个程序在运行。每个原始程序都会获取派生返回的孩子的PID。每个子程序都得到0。然后它们全部printf("Done")

注意

一旦生成程序,它将仅运行所有fork,并获得一堆PID,然后完成打印。碰巧每个叉子都生了一个孩子,但父母却没有注意到,而且对于父母来说,它们基本上是无条件的。