使用pipe()系统调用连接两子进程标准IO的代码问题排查
管道进程通信问题排查与修复
思路正确性分析
你的核心思路没问题:父进程创建管道,先fork第一个子进程重定向标准输出到管道写端,再fork第二个子进程重定向标准输入到管道读端,实现进程间通信。但代码里有几个关键错误导致结果异常。
错误点与修复方案
1. 第二个子进程的管道端搞反了
你在第二个子进程里写的是:
dup2( pipe_name[1],STDIN_FILENO);
pipe_name[1]是管道的写端,但第二个子进程需要从管道读数据,得用管道的读端pipe_name[0],正确代码:
dup2(pipe_name[0], STDIN_FILENO);
2. 缓冲区定义和read调用完全错了
- 你定义的
char words;是单个字符,根本装不下要读的字符串,得改成数组:char words[1000]; read的第二个参数需要是接收数据的指针,你直接传words(字符值)会导致非法内存访问,应该传数组名(本质是指针)- 读取后要手动加字符串终止符
\0,不然printf输出会乱码 - 你用
printf("%d", words)是按整数输出,要输出字符串得用%s
修复后的读取代码:
char words[1000]; ssize_t bytes_read = read(STDIN_FILENO, words, sizeof(words) - 1); if (bytes_read > 0) { words[bytes_read] = '\0'; // 加终止符 } printf("My sibling says:\n %s\n", words);
3. 管道无用端未关闭(规范操作)
每个进程应该关掉不需要的管道端,避免管道引用计数不为0导致的异常:
- 第一个子进程用了写端,关掉读端
close(pipe_name[0]); - 第二个子进程用了读端,关掉写端
close(pipe_name[1]); - 父进程在fork完两个子进程后,关掉管道两端
close(pipe_name[0]); close(pipe_name[1]);
修复后的完整代码
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> int main(int argc, char *argv[]) { int pipe_name[2]; printf("hello world (pid:%d)\n", (int) getpid()); if(pipe(pipe_name) < 0){ printf("mission failed! We'll gettem next time...\n"); exit(1); } int rc = fork(); if (rc < 0) { fprintf(stderr, "fork failed\n"); exit(1); } else if (rc == 0) { // 第一个子进程:重定向stdout到管道写端 close(pipe_name[0]); dup2(pipe_name[1], STDOUT_FILENO); printf("hello, I am child (pid:%d)\n", (int) getpid()); close(pipe_name[1]); exit(0); } else { wait(NULL); int rc2 = fork(); if (rc2 < 0) { fprintf(stderr, "fork failed\n"); exit(1); } else if (rc2 == 0) { // 第二个子进程:重定向stdin到管道读端 close(pipe_name[1]); dup2(pipe_name[0], STDIN_FILENO); char words[1000]; ssize_t bytes_read = read(STDIN_FILENO, words, sizeof(words) - 1); if (bytes_read > 0) { words[bytes_read] = '\0'; } printf("My sibling says:\n %s\n", words); close(pipe_name[0]); exit(0); } else { // 父进程关闭管道两端 close(pipe_name[0]); close(pipe_name[1]); wait(NULL); printf("hello, I am parent of %d (pid:%d)\n", rc2, (int) getpid()); } } return 0; }
修复后的预期输出
hello world (pid:xxxx) hello, I am child (pid:xxxx) My sibling says: hello, I am child (pid:xxxx) hello, I am parent of xxxx (pid:xxxx)
内容的提问来源于stack exchange,提问作者Conan G.
相关产品推荐
相关产品推荐

