如何通过单个管道接收两个子进程返回值并在父进程中求和
问题根因
- 管道本质是字节流传输,只要写入的数据长度小于
PIPE_BUF(Linux下默认4096字节),单个write操作是原子的,不会和其他进程的write穿插。你遇到的不是值覆盖,是父进程只调用了1次read(),只读取了1个int的长度,管道中还残留了另一个子进程写入的int数据未被读取。 - 原有代码还存在两处不规范的资源操作:子进程2未关闭管道读端
fd[0],父进程未关闭不需要的管道写端fd[1],可能引发不必要的资源泄漏或异常。
单管道修复方案
不用更换为多管道,只需要修改父进程的读取逻辑,读取两次int值再求和即可,修改后的代码如下:
#include <sys/types.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> int main(int argc, char *argv[]) { int s1 = 0, s2=0, sum=0; int n= atoi(argv[1]); pid_t child1, child2,wpid; int status = 0 ; int count = 0; int count2 = 0; int fd[2]; if (pipe(fd)< 0){ printf("An error ocurred with opening the pipe\n"); return 1; } child1 = fork(); if(child1<0){ printf("Fork Failed for child 1.\n"); return 1; }else if(child1 == 0){ // 子进程1:关闭不需要的读端 close(fd[0]); while(count<=n){ if(count%2 == 0){ s1 = s1 + count; } count = count + 1; } write(fd[1], &s1, sizeof(int)); close(fd[1]); exit(0); }else{ child2 = fork(); if(child2<0){ printf("failed to fork child 2."); return 1; } if(child2 == 0){ // 子进程2:关闭不需要的读端 close(fd[0]); while(count2<=10){ if(count2%2 != 0){ s2 = s2 + count2; } count2 = count2 +1; } write(fd[1], &s2, sizeof(int)); close(fd[1]); exit(0); }else{ // 父进程:关闭不需要的写端 close(fd[1]); // 等待所有子进程退出 while((wpid = wait(&status))>0); // 读两次,分别取两个子进程的结果 read(fd[0], &s1, sizeof(int)); read(fd[0], &s2, sizeof(int)); sum = s1 + s2; printf("子进程1结果:%d,子进程2结果:%d,二者之和:%d\n", s1, s2, sum); close(fd[0]); } } return 0; }
补充说明
如果需要明确区分两个返回值对应哪个子进程,可以选择两种方案:
- 每个子进程写入的时候带上自己的进程标识,父进程读取后按标识区分
- 创建两个独立的管道,分别对应和两个子进程的通信,避免顺序混淆
内容的提问来源于stack exchange,提问作者weweno
相关产品推荐
相关产品推荐

