使用 fork() 生成进程树

问题描述

我需要创建一个流程树,其中的关系如图所示。

Requirement

问题是我必须按字母顺序创建所有“节点”。我已经走了这么远,但我的订单不一致。我认为我错误地使用了 waitpid

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

int main(int argc,char **argv)
{
  pid_t pidA,pidB,pidC,pidD,pidE,pidF,pidG,pidI;

  pidA = fork();
  if (pidA < 0)
  {
    perror("A");
    exit(1);
  }
  else if (pidA == 0)
  {
    printf("%d: A\n",getpid());

    pidB = fork();
    if (pidB < 0)
    {
      perror("B");
      exit(1);
    }
    else if (pidB == 0)
    {
      printf("%d: B\n",getpid());
      waitpid(pidD,NULL,0);

      pidE = fork();
      if (pidE < 0)
      {
        perror("E");
        exit(1);
      }
      else if (pidE == 0)
      {
        printf("%d: E\n",getpid());
        waitpid(pidG,0);

        pidI = fork();
        if (pidI < 0)
        {
          perror("E");
          exit(1);
        }
        else if (pidI == 0)
        {
          printf("%d: I\n",getpid());
        }
        else
        {
          ;
        }
      }
      else
      {
        pidF = fork();
        if (pidF < 0)
        {
          perror("F");
          exit(1);
        }
        else if (pidF == 0)
        {
          printf("%d: F\n",getpid());
        }
        else
        {
          ;
        }
      }
    }
    else
    {
      pidC = fork();
      if (pidC < 0)
      {
        perror("B");
        exit(1);
      }
      else if (pidC == 0)
      {
        printf("%d: C\n",getpid());
        waitpid(pidF,0); // !

        pidG = fork();
        if (pidG < 0)
        {
          perror("G");
          exit(1);
        }
        else if (pidG == 0)
        {
          printf("%d: G\n",getpid());
        }
        else
        {
          ;
        }
      }
      else
      {
        pidD = fork();
        if (pidD < 0)
        {
          perror("B");
          exit(1);
        }
        else if (pidD == 0)
        {
          printf("%d: D\n",getpid());
        }
        else
        {
          ;
        }
      }
    }
  }
  else
  {
    ;
  }

  return 0;
}

输出不一致,所以我认为这部分没有多大帮助。

5644: A
5645: B
5646: C
5647: D
5648: G
5650: F
5649: E
5651: I

解决方法

这里的主要问题是 waitpid 仅在所有进程线性相关(即父进程、子进程、“孙子”进程等)时才满足同步。

但是,如图所示,您的流程并不是线性相关的。当您从 B 进程中调用 waitpid(pidD,NULL,0); 时,您会发现此问题出现。在此上下文中不仅没有定义 pidD,而且 D 进程不是 B 进程的子进程,因此 waitpid 是不合适的。

@EOF 提出了一个很好的观点,即尝试串联运行多个进程违背了拥有多个进程的目的。但是,如果您只是想将此练习作为一个有趣的脑筋急转弯来进行,我建议您在原始进程中设置 pipe,然后在适当的进程想要发出它已退出的信号时关闭写入端。等待第一个进程结束的进程可以在读取端调用 select