管道输出到C中的fork

问题描述

我在编中有多个进程,我希望按顺序将输出一个进程传递到另一个进程。我相信我已经将一个进程的stdin链接到前一个进程的读取端,并将stdout链接到管道的写端。我仍然没有看到输出。我在这里链接中缺少什么吗?

  int pipeFds[numProg][2];
  
  for (int i = 0; i < numProg; i++) {
    if (pipe(pipeFds[i]) != 0) { // create pipe for each process
      printf("Failed to create pipe!");
      exit(1);
    }
    child_pid = fork();
    if (child_pid == -1) {
      printf("Error while creating fork!");
      exit(1);
    } 
    if (child_pid == 0) {
      if (i == 0) { 
        close(pipeFds[i][READ_END]); // close STDIN first process since it does not read
      } else { 
        // change stdin to read end of pipe for intermediary processes
        close(pipeFds[i]);
        dup2(pipeFds[i - 1][READ_END],STDIN_FILENO);
      }
      dup2(pipeFds[i][WRITE_END],STDOUT_FILENO); // change stdout to write end of pipe
      execvp(progs[i][0],(char *const * )progs[i]);
    } else {
      // parent process stuff
    }
  }
  
  // Close pipes except last pipe for EOF
  for (int i = 0; i < numProg - 1; i++) {
    close(pipeFds[i][READ_END]);
    close(pipeFds[i][WRITE_END]);
  }

解决方法

  1. 您的代码包含一个流浪get

  2. 您必须关闭close(pipeFds[i]);中的管道。使用您的代码,每个孩子都会使先前孩子中的// parent process stuff保持打开状态。例如

    pipeFds
  3. 使用一对 } else { // parent process stuff if (i > 0) close(pipeFds[i - 1][READ_END]); close(pipeFds[i - 1][READ_END]); } 而不是fds[2]对可能更有效。

,

请记住,您需要在每个流程中关闭所有管道,以使其正常工作。

示例:

如果numProg=2创建2个管道和2个子进程。添加父级后,将运行3个进程,并且在每个进程中,您最终需要关闭所有管道。

对于child_pid==0,您需要关闭[READ_END],但不要关闭[WRITE_END]

对于child_pid==1,您执行close(pipeFds[1])。您需要指定[READ_END][WRITE_END]

然后,每个子进程都通过execvp退出,但是如果失败,它可能会返回控制权。在man页面上:

exec()系列函数将当前过程映像替换为新的过程映像。 .. exec()函数仅在发生错误时返回。

因此,您可能希望在_exit(0);之后添加execvp,以确保即使execvp失败,每个子进程也会正确退出。

父进程将关闭除最后一个管道之外的所有管道。因此,在NumProg=2的示例中,[READ_END]的{​​{1}}和[WRITE_END]都不会关闭。

最后,父流程应该pipeFd[1]以便所有子流程关闭(使用wait),否则您可能最终会遇到僵尸或孤立的流程。