【问题标题】:Unix process fork hierarchyUnix 进程分叉层次结构
【发布时间】:2018-10-10 18:35:27
【问题描述】:

需要实现这个this hierarchy of processes

每个有子进程的进程都不能在其子进程之前终止。在 由“info()”函数显示的消息条款,一个 END 消息 父级不应出现在其子级的任何 END 消息之前。 info 函数看起来像这样info(BEGIN | END, process_no, thread_no);

int main() {
    init();
    pid_t  pid2, pid3, pid4,pid5,pid6,pid7,pid8,pid9;
    info(BEGIN,1,0);

    pid2 = fork();
    if ( pid2 == 0 ) {
        // P2 child
        info(BEGIN,2,0);
        pid5 = fork();
        if ( pid5 == 0 ) {  // P5 child
            info(BEGIN,5,0);
            pid9 = fork();
            if(pid9 == 0){ // P9 child
                info(BEGIN,9,0);
                info(END,9,0);
            }
            waitpid(pid9,'\0','\0');
            info(END,5,0);
            // grandchild (of top-level parent)
        } else {
            waitpid(pid5,'\0','\0');
            info(END,2,0);
        }
    } else if((pid3 = fork()) == 0) {
        info(BEGIN,3,0); // P3 child
        pid4 = fork();
        if(pid4 == 0){ //P4 child
            info(BEGIN,4,0);
            info(END,4,0);
        }else{
            pid6 = fork();
            if(pid6 == 0){ //P6 child
                info(BEGIN,6,0);
                pid7 = fork();
                if(pid7 == 0){ //P7 child
                    info(BEGIN,7,0);
                    info(END,7,0);
                }
                waitpid(pid7,'\0','\0');
                info(END,6,0);
            }
        }
        waitpid(pid4,'\0','\0');
        waitpid(pid6,'\0','\0');
        info(END,3,0);
    }
    else{
        pid8=fork();
        if(pid8 == 0){ //P9 child
            info(BEGIN,8,0);
            info(END,8,0);
        }
        waitpid(pid2,'\0','\0');
        waitpid(pid3,'\0','\0');
        waitpid(pid4,'\0','\0');
        waitpid(pid5,'\0','\0');
        waitpid(pid6,'\0','\0');
        waitpid(pid7,'\0','\0');
        waitpid(pid8,'\0','\0');
        waitpid(pid9,'\0','\0');
        info(END, 1, 0);
    }

    for(int i=0; i<8; i++){ 
        wait(NULL);  
    }

    return 0;
}

我的输出是

[ ] BEGIN P1 T0 pid=4370 ppid=4122 tid=1184286464
[ ] BEGIN P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ] BEGIN P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ]  END  P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ]  END  P1 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ]  END  P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ]  END  P3 T0 pid=4375 ppid=4372 tid=1184286464
[ ]  END  P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ] BEGIN P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P5 T0 pid=4377 ppid=4374 tid=1184286464
[ ]  END  P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P6 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ]  END  P3 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ]  END  P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ]  END  P3 T0 pid=4376 ppid=4372 tid=1184286464
[ ]  END  P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ]  END  P1 T0 pid=4370 ppid=4122 tid=1184286464

预期输出:

[ ] BEGIN P1 T0 pid=4370 ppid=4122 tid=1184286464
[ ] BEGIN P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ] BEGIN P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ] BEGIN P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ]  END  P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ] BEGIN P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ]  END  P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ]  END  P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ] BEGIN P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P5 T0 pid=4377 ppid=4374 tid=1184286464
[ ]  END  P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P6 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P3 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ]  END  P1 T0 pid=4370 ppid=4122 tid=1184286464

我试图弄清这个问题将近 2 个小时,但不明白哪里不顺利,我认为它与 waitpid 有关,但无法弄清楚......

【问题讨论】:

    标签: c multithreading unix fork


    【解决方案1】:

    最大的问题是你启动了所有这些进程,但你从来没有结束它们。

    以最后一个else 子句为例。在该块中,您调用fork 来创建pid8。然后您有进程 8 打印 BEGIN 和 END,但随后它不退出,它继续进入后续代码,这显然是针对 P1 的(它将毫无意义地为进程调用 waitpid它没有创建)。而且,它会在info(END,1,0) 调用中出错。同样的事情发生在其他几个代码路径中。

    一些建议:

    1. 仅在一个进程中调用waitpid,以用于那些被创建为直接子进程的进程。无论如何,这些是您唯一可以成功调用waitpid 的。例如,P1 不能等待它没有创建的 P4。

    2. 将 NULL 作为附加参数传递给 waitpid not '\0'。 (后者恰好适用于大多数 C 实现,因为字符 '\0' 的表示与那些实现中 NULL 指针的表示相同,但​​它不正确:您应该传递一个指向整数 [或特殊值 NULL] 不是 char 值。)

    3. 检查系统调用的返回状态。如果你这样做了,你会看到很多waitpid 调用都失败了。 (在这种特殊情况下,这实际上并没有导致问题,但检查并打印出故障总是一个好主意,因为它们会提示您为什么程序不能像您一样工作期待。)

    4. 最重要的是,在每个if (pidX == 0) { 子句中,在执行完该块应该执行的任何其他操作后,放入exit(0) 语句以使进程退出:

      pid8=fork();
      if(pid8 == 0){
          info(BEGIN,8,0);
          info(END,8,0);
          exit(0);          /* <<<<<<============ */
      }
      


    最终建议: 选择一种编码风格并坚持下去。你有

    pid8=fork();
    if(pid8 == 0){
    

    你有

    pid2 = fork();
    if ( pid2 == 0 ) {
    

    你有

    if((pid3 = fork()) == 0) {
    

    都在同一个短节目中。也就是说,您正在以不同的方式组合一组基本相同的操作,然后在程序中以不同的间距对它们进行编码。这对编译器没有任何影响,但它对试图阅读您的代码的人有很大的不同(如果您编写了足够的代码,这将包括您自己)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-24
      • 1970-01-01
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多