pipe()与fork()使用问题:/bin/cat报Bad file descriptor错误
咱们一步步拆解你代码里的问题,然后帮你实现「通过管道在子进程间传值并修改」的需求~
你的代码里的核心问题
1. 管道根本没创建!
你定义了fd1[2]但完全没调用pipe(fd1)初始化管道!这会导致文件描述符都是无效值,后续的dup2和读写操作自然会抛出「Bad file descriptor」错误,这也是/bin/cat报错的核心原因。
2. 对fork()后变量的误解
fork()执行后,每个子进程都会拿到父进程地址空间的独立副本——也就是说,子进程1里的line和子进程2里的line是完全不相干的两个变量。你在子进程2里直接line++,修改的只是自己进程里的局部变量,根本没用到管道传递过来的值。
3. 子进程2的逻辑顺序完全错了
你先做了line++和printf,才把管道读端重定向到标准输入,之后调用cat——但cat是从标准输入读内容再输出,而你根本没从管道里读取子进程1发送的数据,更别说修改它了。
4. 父进程没等子进程跑完就退出
父进程直接exit(0),没调用wait()或waitpid()等待子进程完成,可能导致子进程还没执行完,父进程就退出了,引发输出混乱或者僵尸进程。
修正后的代码实现
下面是修改后的代码,完美实现「子进程1传值到管道,子进程2读取后修改输出」的需求:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<string.h> #include<sys/wait.h> #include<errno.h> #define READ_END 0 #define WRITE_END 1 int main() { int fd1[2]; // 第一步:必须先创建管道! if (pipe(fd1) == -1) { perror("pipe failed"); exit(EXIT_FAILURE); } int line = 1; // 子进程1:把数值转成字符串写入管道 if(fork() == 0) { close(fd1[READ_END]); // 子进程1不需要读端,直接关闭 char buffer[100]; snprintf(buffer, sizeof(buffer), "%d", line); write(fd1[WRITE_END], buffer, strlen(buffer)); close(fd1[WRITE_END]); exit(EXIT_SUCCESS); } // 子进程2:读取管道数据,修改后输出 if (fork() == 0) { close(fd1[WRITE_END]); // 子进程2不需要写端,直接关闭 char buffer[100]; ssize_t bytes_read = read(fd1[READ_END], buffer, sizeof(buffer)-1); if (bytes_read == -1) { perror("read failed"); exit(EXIT_FAILURE); } buffer[bytes_read] = '\0'; // 手动补字符串结束符 // 把读取到的字符串转成整数,修改后输出 int received_num = atoi(buffer); received_num++; printf("子进程1发送的值:%d\n", atoi(buffer)); printf("子进程2修改后的值:%d\n", received_num); close(fd1[READ_END]); exit(EXIT_SUCCESS); } // 父进程:关闭管道两端,等待所有子进程执行完毕 close(fd1[READ_END]); close(fd1[WRITE_END]); wait(NULL); // 等待第一个子进程 wait(NULL); // 等待第二个子进程 return 0; }
关键修改点说明
- 初始化管道:添加了
pipe(fd1)调用,并检查返回值确保管道创建成功,这是管道通信的基础。 - 子进程1直接写管道:用
write()直接写入数据,比printf更可靠(printf有缓冲机制,可能导致数据没及时发送到管道)。 - 子进程2读取并修改:先从管道读取子进程1的传值,转成整数后修改,再输出——这才是真正利用管道传递并修改值的逻辑。
- 父进程等待子进程:调用两次
wait(NULL)确保子进程都执行完再退出,避免输出混乱和僵尸进程。
关于你尝试的/bin/cat
如果只是想验证管道数据,你可以让子进程2把管道读端重定向到标准输入后调用cat,这样cat会直接输出管道里的内容,但cat只能读取输出,无法修改数据。如果要实现修改逻辑,必须自己处理读取、转换、修改的步骤,就像上面的代码那样。
内容的提问来源于stack exchange,提问作者kirito kun
相关产品推荐
相关产品推荐

