关于从 multi-child 进程读取数据的管道问题

Pipe issue about reading data from multi-child process

pid_t kids[argc];
int childCount = argc - 1;
int fd[2];
/* create the pipe*/
if (pipe(fd) == -1) {
    fprintf(stderr ,"Pipe failed");
    return 1;
for(i=0; i < childCount; i++) {
   kids[i] = fork();
   if(kids[i] < 0){
      //fork fail
   }
   else if(kids[i] == 0) {
     /* child process */
        sum = max + min;//sum and dif are results from each child process
        dif = max - min;
        /* close the unused end of pipe, in this case, the read end */
        close(fd[READ_END]);
        /* write to the pipe */
        write(fd[WRITE_END], &sum, sizeof(sum));
        write(fd[WRITE_END], &dif, sizeof(dif));
        /* close write end */
        close(fd[WRITE_END]);
        exit(0);
   }
   else {
        waitpid(kids[i], &status, 0);
        close(fd[WRITE_END]);

        read(fd[READ_END], &sum, sizeof(float));
        read(fd[READ_END], &dif, sizeof(float));
        close(fd[READ_END]);
   }
}

以上是代码,简化了一点
我想做的是等待任何 child 完成并处理其数据,然后重复此操作直到所有 children 完成。
有人能告诉我如何将 children 生成的数据传输到 parent 吗?

你没有提到你当前代码的问题是什么,而且你显示的代码没有编译,所以我只能猜测这是你真实代码的近似值。

尽管如此,还是引起了我的注意:

永远不要在循环之前关闭 if (pipe(fd) == -1) 的主体,这意味着循环是 if 主体的一部分。这可能不是您想要的,尽管我不确定这是否是拼写错误/复制粘贴错误。也许在实际代码中你确实关闭了 if.

父进程的代码是错误的:因为它是运行在for循环中,你在管道的读写端重复调用close(2)。这将导致 close(2) 到 return 一个错误 (EBADF),您在循环的第二次迭代时公然忽略它。同样在第二次迭代中,分叉的子进程将尝试关闭不再存在的管道的读取通道(因为我们刚刚分叉的父进程在再次分叉之前在前一次迭代中关闭了两端),然后它试图写入不存在的管道。

要修复它,您必须确保父级在每个子级都完成之前不会关闭管道。不要 close(2) 在父循环内;相反,在循环之后执行:

for(i=0; i < childCount; i++) {
   kids[i] = fork();
   if(kids[i] < 0){
      //fork fail
   }
   else if(kids[i] == 0) {
     /* child process */
        sum = max + min;//sum and dif are results from each child process
        dif = max - min;
        /* close the unused end of pipe, in this case, the read end */
        close(fd[READ_END]);
        /* write to the pipe */
        write(fd[WRITE_END], &sum, sizeof(sum));
        write(fd[WRITE_END], &dif, sizeof(dif));
        /* close write end */
        close(fd[WRITE_END]);
        exit(0);
   }
   else {
        waitpid(kids[i], &status, 0);
        read(fd[READ_END], &sum, sizeof(float));
        read(fd[READ_END], &dif, sizeof(float));
   }
}

close(fd[READ_END]);
close(fd[WRITE_END]);

由于您在循环中等待每个子进程终止,因此可以保证您不会在仍有活动编写器时关闭管道。