管道输出到 C 中的 fork

Piping output to forks in C

我在 progs 中有多个进程,我希望将输出从一个进程按顺序传输到另一个进程。我相信我已经将一个进程的标准输入链接到前一个进程的读取端,并将标准输出链接到管道的写入端。我仍然没有看到输出。我是否遗漏了此处的链接?

  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. 您的代码包含一个杂散的 close(pipeFds[i]);

  2. 您必须关闭 // parent process stuff 内的管道。使用您的代码,每个 child 保持前一个 children 的 pipeFds 打开。例如

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

记住你需要关闭所有个管道,在每个进程中,它才能工作。

示例:

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

对于 child_pid==0,您关闭 [READ_END] 但永远不会关闭 [WRITE_END]

对于 child_pid==1 你做一个 close(pipeFds[1])。您需要指定 [READ_END][WRITE_END].

然后每个子进程通过 execvp 退出,但是,如果它失败,则可能 return 控制。来自 man 页面:

exec() 系列函数用新的过程映像替换当前过程映像。 .. 如果发生错误,exec() 函数仅 return。

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

父进程关闭除最后一个以外的所有管道。所以在 NumProg=2 的例子中,pipeFd[1][READ_END][WRITE_END] 都永远不会关闭。

最后,父进程应该 wait 关闭所有子进程(使用 while(wait(NULL) != -1);),否则你可能会得到僵尸或孤儿进程。