execvp重定向stdout问题:进程树中scanf无法读取父进程输出
进程二叉树管道通信问题修复
这段代码是用进程作为节点构建二叉树的一个片段,目标是通过中序遍历将数据传递给左子树。当前逻辑仅创建左子进程并再次执行./tpipe可执行文件,但执行./tpipe 0时,子进程中的scanf读取的是用户输入而非父进程printf输出的字符串。要求必须用dup2而非read/write等方法修复,因为每次启动程序时filedp都会重新初始化。
原精简代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <assert.h> #include <sys/wait.h> int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "NEED MORE ARGUMENT\n"); return 1; } int curDepth = atoi(argv[1]); int filedp[2]; pipe(filedp); if (curDepth != 0) { char buf[100]; scanf("%s", buf); fprintf(stderr, "buf is: %s\n", buf); } if (curDepth < 1) { int fd = fork(); if (fd == 0) { close(filedp[0]); dup2(filedp[1], STDOUT_FILENO); dup2(filedp[0], STDIN_FILENO); printf("Example\n"); char *k[] = {"./tpipe", "1", NULL}; execvp("./tpipe", k); } else { wait(NULL); // parent } } else { fprintf(stderr, "IT IS LEAF!\n"); } return 0; }
问题分析
原代码的核心错误在于管道重定向逻辑混乱:
- 子进程同时将STDOUT和STDIN绑定到管道的不同端,导致输出和输入的流向完全错误
- 父进程没有将自身输出定向到管道,无法把数据传递给子进程
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <assert.h> #include <sys/wait.h> int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "NEED MORE ARGUMENT\n"); return 1; } int curDepth = atoi(argv[1]); int filedp[2]; pipe(filedp); if (curDepth != 0) { char buf[100]; scanf("%s", buf); fprintf(stderr, "buf is: %s\n", buf); } if (curDepth < 1) { int fd = fork(); if (fd == 0) { // 子进程只需读取管道数据,关闭写端并将STDIN重定向到管道读端 close(filedp[1]); dup2(filedp[0], STDIN_FILENO); close(filedp[0]); char *k[] = {"./tpipe", "1", NULL}; execvp("./tpipe", k); perror("execvp failed"); exit(1); } else { // 父进程只需写入管道数据,关闭读端并将STDOUT重定向到管道写端 close(filedp[0]); dup2(filedp[1], STDOUT_FILENO); close(filedp[1]); printf("Example\n"); wait(NULL); } } else { fprintf(stderr, "IT IS LEAF!\n"); } return 0; }
修复说明
- 分工明确管道读写:父进程负责向管道写入数据,子进程负责从管道读取数据,避免双向绑定的逻辑混乱
- 正确重定向标准流:
- 子进程将STDIN重定向到管道读端,这样
scanf会自动读取管道中的父进程输出 - 父进程将STDOUT重定向到管道写端,这样
printf的内容会直接写入管道
- 子进程将STDIN重定向到管道读端,这样
- 关闭冗余文件描述符:重定向完成后关闭原管道描述符,避免资源泄漏,同时确保管道在进程退出时能正确触发EOF
内容的提问来源于stack exchange,提问作者Özgür Çavuşoğlu
相关产品推荐
相关产品推荐

