【问题标题】:Fork() Parent and ChildFork() 父子
【发布时间】:2014-04-16 17:05:37
【问题描述】:

我需要的是有 3 个孩子和 1 个父母(主程序),因为孩子和父母将有不同的功能。 我不知道为什么我不能正确地做到这一点,据我所知,当你执行 fork() 时,如果它返回 0,则执行子代码,否则执行父代码。 所以,这是我的程序:

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

int
main(int argc, char ** argv) {

   printf ("Init Parent. PID =%d\n", getpid());

   fork();
   fork();
   if (fork() == 0) {
   printf ("Init Child. PID =%d\n", getpid());
    sleep(1);

   } else {        
    printf ("I am the parent. PID = %d\n",getpid()); 
    sleep(1);

   }
    exit(0);
}

这是输出:

Init Parent. PID =9007
I am the parent. PID = 9007
I am the parent. PID = 9009
Init Child. PID =9010
Init Child. PID =9011
I am the parent. PID = 9008
I am the parent. PID = 9012
Init Child. PID =9013
Init Child. PID =9014

这就是我想要的:

Init Parent. PID =9007
I am the parent. PID = 9007
Init Child. PID =9010
Init Child. PID =9011
Init Child. PID =9013
Init Child. PID =9014

我不知道为什么它说我是父母 3 次以及如何正确地做到这一点,因为 1

if (fork() == 0) 

看起来很糟糕。

非常感谢任何帮助,在此先感谢您。

【问题讨论】:

    标签: c process fork parent-child


    【解决方案1】:

    您必须从第一次分叉后开始检查父子节点。 每次您拨打fork() 时,您都在产卵。你现在做的是这样的:

    • 开始执行 1 个程序(+1 个过程,总共 1 个过程)
    • 第一个fork():主程序产生子程序(+1 个进程,总共 2 个进程)
    • 第二个fork():子主程序产生子程序。 (+2 触发,总共 4 触发)
    • 第三个fork()所有之前提到的进程都会产生子进程(+4 个进程,总共 8 个进程)。

    您的原始代码生成的进程树如下所示:

          pi
        /  |  \
       pi  pi  pi
      / |  |  
     pi pi pi
     |
     pi
    

    可能的解决方案(适用于 n 个孩子):

    int noProcs = 3;
    int i;
    for (i = 0; i < noProcs; ++i) {
      if (fork() == 0) {
        printf("in child\n");
        //Do stuff...
        exit(0);
       }
     }
     //DONT FORGET: Reap zombies using wait()/waitpid()/SIGCHLD etc...
    

    请注意,在每次fork() 调用之后,生成的子代都将执行相同的后续代码。对于循环迭代中的每一步,在我使用fork() 生成一个孩子后会发生以下情况:

    • 子进程:执行子代码,调用exit()。这可以防止我们循环并创建比预期更多的孩子。
    • 父进程:绕过if(fork() == 0) 语句的主体并逐步执行循环,生成指定的其他子进程。

    【讨论】:

    • 谢谢你,我认为我将使用那个结构来实现我的目标,但是有一个问题,你能告诉我为什么如果我在 exit(0) 之前放一个 slee(1) 它不起作用??
    • 当我 sleep() 进程时它不起作用,它只是不起作用 sleep() ,你知道为什么吗?
    • @user3515313 你睡在子进程(它在不同的线程上运行),而不是父进程,这就是它不明显的原因。
    • 嗯,是的,你说得对,这很有道理,非常感谢,那你怎么睡孩子?
    【解决方案2】:

    fork 复制调用它的进程,创建一个处于完全相同状态并继续在同一点运行的新(子)进程。父子之间的唯一区别是 fork 调用返回的内容。

    因此,请考虑一下您的代码会发生什么。您从一个流程开始:

    printf ("Init Parent. PID =%d\n", getpid());
    

    以便一个进程打印一条消息

    fork();
    

    你 fork,所以现在有两个进程(父进程和子进程)

    fork();
    

    两个进程都分叉,因此您现在有 4 个进程(父进程、2 个子进程和孙子进程)

    if (fork() == 0) {
    

    再次分叉,因此您现在有 8 个进程——父进程、3 个子进程、3 个孙子进程和一个曾孙进程。其中一半(一个孩子、两个孙子和曾孙)从这个分叉中返回 0,因为他们是第三个分叉创建的孩子。另一半是父母。

    所以在这 3 个分叉之后,你有 8 个进程,其中 4 个会打印“Init Child”,其中 4 个会打印“I am the parent”

    如果您只想要 3 个直系子代(并且没有孙子代),您需要安排您的代码,使子代不再调用 fork。你可以使用类似的东西:

    if (fork() && fork() && fork())
        printf ("I am the parent. PID = %d\n",getpid());
    else
        printf ("Init Child. PID =%d\n", getpid());
    

    【讨论】:

      【解决方案3】:

      修改代码如下。

      您需要检查每个 fork() 的返回码,而不仅仅是最后一次调用 fork。我没有跑去尝试,但这是我觉得的错误。 你说 - 你需要 1 个父母和 3 个孩子 - 所以在第一个 fork() 期间 - 将创建 1 个孩子,然后对于第二个 fork() - 将创建 1 个孩子的孙子和 1 个父母的孩子。

      编辑:

            parent
             /   \  
         fork-1  fork-2
            |      |
          child1  child-2
            |
          fork-2
            |
          child3 
      
      
      for(int i=0;i<2;i++)
      {
         if (fork()==0)
            printf ("Init Child. PID =%d\n", getpid());
            sleep(1);
         } else {
            printf ("I am the parent. PID = %d\n",getpid()); 
            sleep(1);
         }
      }
      

      【讨论】:

      • 嗨,谢谢你的回答,但这是输出:我是家长。 PID = 9487 初始化子。 PID =9488 我是家长。 PID = 9487 我是家长。 PID = 9488 初始化子。 PID = 9490 初始化孩子。 PID =9491 我是家长。 PID = 9490 我是父母。 PID = 9488 初始化子。 PID =9494 我是家长。 PID = 9487 初始化子。 PID = 9493 初始化孩子。 PID = 9495 初始化孩子。 PID =9492 我是父母。 PID = 9491。是一样的,它说父母有 3 个不同的 pid 对不起,我不知道如何分隔行
      • @user3515313 - 你需要你的父母只做一次,三个孩子应该做一次。请根据您的需要编辑问题。将根据需要编辑代码。
      猜你喜欢
      • 2012-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多