【问题标题】:waitpid() error problemwaitpid() 错误问题
【发布时间】:2018-10-07 05:03:45
【问题描述】:

我写了代码来打印 pidparent->g3->c2->g1->g2->c1.

所以我使用了wait()waitpid()。但我失败了。

所以我写了“完成”代码来了解问题所在。

而且我知道 c1 会忽略 waitpid 并打印 what->finish。

我该如何解决这个问题


#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

void main()
{
pid_t c1,c2,g1,g2,g3;

printf("parent:%d\n", (int)getpid());
c1=fork();
int status;
if (c1>0) {
        c2=fork();
        if (c2==0) {
            g3=fork();
            if (g3==0) {
                    printf("g3:%d\n",(int)getpid());
            } else if (g3>0) {
            wait(&status);
            printf("c2:%d\n",(int)getpid());
            }
       }
} else if (c1==0) {
        waitpid(c2,&status,WUNTRACED);
    printf("what\n");
    g1=fork();
    if (g1>0) {
            g2=fork();
            if (g2==0) {
                printf("g2:%d\n",(int)getpid());
            } else if (g2>0) {
                    waitpid(g1,&status,WUNTRACED);
                    printf("c1:%d\n", (int)getpid());
            }
        } else if (g1==0) {
            waitpid(g2,&status,WUNTRACED);
            printf("g1:%d\n",(int)getpid());
            } else {
                printf("failed\n");
                exit(1);
            }
} else {
    printf("main failed\n");
    exit(1);
} printf("finish\n");
}

【问题讨论】:

    标签: fork wait


    【解决方案1】:
    pid_t c1,c2,g1,g2,g3;
    
    printf("parent:%d\n", (int)getpid());
    c1=fork();
    int status;
    if (c1>0) {
         ....
    } else if (c1==0) {
            waitpid(c2,&status,WUNTRACED);
    

    c2 变量从未设置,因此它可能包含它碰巧在堆栈上的任何垃圾。如果您使用 -Wall 标志运行它,编译器会警告您。

    另外,您应该始终检查waitpid的返回值;那也会发现这个错误。

    fork 之后,不要假设子节点将被安排在父节点之前运行,反之亦然。

        printf("what\n");
        g1=fork();
        if (g1>0) {
                ...
            } else if (g1==0) {
                waitpid(g2,&status,WUNTRACED);
    

    同上,g2 变量在没有被初始化的情况下被使用。

    另外,main 的返回值应该是int,而不是void

    并且您应该始终使用-O2 -Wextra -Wall 标志进行编译,这将为您省去很多麻烦。如果您发现一些警告是多余的,您可以单独关闭它们;例如。 (-Wno-parentheses, -Wno-unused)。

    【讨论】:

      【解决方案2】:

      我用gcc 6.3.0 验证了这段代码,它在那里正常工作。 好吧,这段代码按照您要求的顺序打印它们:

      #include <stdio.h>
      #include <unistd.h>
      #include <sys/wait.h>
      #include <stdlib.h>
      #include <sys/mman.h>
      #include <sys/types.h>
      
      static int *glob_var;
      
      int main()
      {
      int c1,c2,g1,g2,g3;
      glob_var = mmap(NULL, sizeof *glob_var, PROT_READ | PROT_WRITE, 
                      MAP_SHARED | MAP_ANONYMOUS, -1, 0);
      printf("parent:%d\n", (int)getpid());
      *glob_var = 0;
      c1=fork();
      int status;
      if (c1>0) {
              c2=fork();
              if (c2==0) {
                  g3=fork();
                  if (g3==0) {
                      printf("g3:%d\n",(int)getpid());
                  } else if (g3>0) {
                  wait(&status);
                  printf("c2:%d\n",(int)getpid());
                  *glob_var = 1;
                  }
         }
      } else if (c1==0) {
             while(*glob_var == 0);
      
          printf("what\n");
          g1=fork();
          if (g1>0) {
              waitpid(g1,&status,WUNTRACED);
              g2=fork();
      
              if (g2==0) {
      
                  printf("g2:%d\n",(int)getpid());
              } else if (g2>0) {
                      waitpid(g2,&status,WUNTRACED);
                      printf("c1:%d\n", (int)getpid());
              }
          } else if (g1==0) {
      
              printf("g1:%d\n",(int)getpid());
              } else {
                  printf("failed\n");
                  exit(1);
              }
      } else {
          printf("main failed\n");
          exit(1);
      }
      
      }
      

      我做了一些chagnes。

      我刚刚在开头添加了waitpid(g2,&amp;status,WUNTRACED);

       else if (g2>0) {
                  waitpid(g2,&status,WUNTRACED);
                  printf("c1:%d\n", (int)getpid());
          } 
      

      条件语句,因此 g2 将在 c1 之前完成。

      并在条件语句if(g1&gt;0)中添加waitpid(g1,&amp;status,WUNTRACED);,因此g1将在g2之前完成。

      我还使用了glob_var,它是一个声明为static int *glob_var; 的全局变量,并使用mmap 在父子之间共享它。

       glob_var = mmap(NULL, sizeof *glob_var, PROT_READ | PROT_WRITE, 
                  MAP_SHARED | MAP_ANONYMOUS, -1, 0);
      

      并使用它作为信号量在c1 之前执行c2 并且它的工作方式就像当c2 完成时它将信号量的值从0 更改为1 之后只有while(*glob_var == 0) 循环将打破else if(c1==0) 条件将继续。

      而且else if (c1==0) 中也不需要waitpid(c2,&amp;status,WUNTRACED);,所以我删除了它。

      【讨论】:

        猜你喜欢
        • 2012-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-05
        • 2021-05-18
        • 2020-05-22
        相关资源
        最近更新 更多