【问题标题】:Understanding how UNIX fork() affects parent process了解 UNIX fork() 如何影响父进程
【发布时间】:2018-10-02 16:50:19
【问题描述】:

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

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

我试图了解上述程序如何打印 'Done' 8 次,因为输出。

【问题讨论】:

  • 你有一个父进程。首先fork() 创建一个子进程。第二个fork() 由父进程和子进程都执行,因此您创建了两个额外的进程,依此类推。
  • "...上面的程序打印 'Done' 8 次..." - 错误!上面的程序打印“完成”ONCE。孩子们每人打印一次“完成”... TO THE SAME CONSOLE(“StdOut”)。您的子进程也会创建子进程:第一个孩子:两个孩子,第二个孩子,一个。他们的孩子创造孩子。因此,总共是“8”。
  • @paulsm4 Jee,不要用大写和斜体字了。
  • 另外一点 - 孩子fork() 影响父母的ONLY 方式是将孩子的PID 返回给父母。无论如何你都没有使用它:(
  • 您可以使用int pid1 = fork(); int pid2 = fork(); int pid3 = fork(); 捕获来自fork() 的返回值,然后打印所有信息:printf("Done: PID = %d, PPID = %d, pid1 = %d, pid2 = %d, pid3 = %d\n", (int)getpid(), (int)getppid(), pid1, pid2, pid3);,从而更好地跟踪正在发生的事情。正确解释,这将使发生的事情更加清晰——您将知道哪个进程打印了每一行输出。 (唯一的问题可能是不同进程之间的隔行打印;如果它成为一个常规问题,那就更难解决了。)

标签: c unix fork


【解决方案1】:

您应该注意,每个后续分叉都将由之前创建的子代执行。所以流程层次结构如下:

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 个。

【讨论】:

    【解决方案2】:

    当通过调用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() 通过复制 调用创建一个新进程 过程。这 新进程,称为子进程,是 调用进程

    【讨论】:

      【解决方案3】:

      我会让它更直观一点:

      第一步

      // 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                    |                |
      }                                                  |                |
      

      第三步

      当 Program 1 Version 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
      }
      

      第四步

      每个最终的分叉都会再次复制每个程序,从而使您有 8 个程序在运行。每个原始程序都获取由 fork 返回的孩子的 PID。每个子程序得到0。然后他们都printf("Done")

      注意

      一旦生成了一个程序,它就会运行所有的 fork 并获取一堆 PID,然后打印完成。碰巧每个叉子都会生一个孩子,但父母没有注意到,他们基本上对父母来说是 NO-OP。

      【讨论】:

        猜你喜欢
        • 2014-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-12
        • 1970-01-01
        相关资源
        最近更新 更多