如何通过pipe()实现exec启动的子进程与父进程通信?代码问题排查
问题根源
- 你遇到的首先是编译错误:
link是main.c中定义的局部变量,每个进程拥有独立的虚拟地址空间,exec执行新程序时会完全替换原进程的用户空间数据,新程序根本感知不到原进程中的link变量定义,因此直接报变量未定义错误。 - 你对管道继承的理解是完全正确的:fork后子进程会继承父进程打开的所有文件描述符,exec执行时默认也不会关闭已打开的文件描述符,问题出在你不知道新进程里对应管道写端的文件描述符数值,且错误地尝试调用父进程的局部变量。
修复方案
这里提供两种可行的实现方式:
方法1:利用已做的标准输出重定向(改动最小)
你在子进程中已经调用dup2(link[1], STDOUT_FILENO)将管道写端绑定到了标准输出(固定文件描述符编号为1),直接修改exec.c往标准输出写数据即可,无需修改main.c:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/shm.h> int main(int argc, char *argv[]) { char a = 'A'; // 标准输出已经被重定向到管道,直接写即可 write(STDOUT_FILENO, &a, sizeof(a)); return 0; }
编译运行后可以得到预期输出:Output: (A)
方法2:传递文件描述符参数(不占用标准输出)
如果不想重定向标准输出,可以把管道写端的文件描述符作为启动参数传给exec程序,注意不要在exec调用前关闭该描述符:
- 先修改main.c的子进程逻辑:
if (pid == 0) { // 只关读端,保留写端传给exec程序 close(link[0]); // 将文件描述符转成字符串作为启动参数 char fd_arg[16]; sprintf(fd_arg, "%d", link[1]); char *exec_argv[] = {"./exec", fd_arg, NULL}; execvp("./exec", exec_argv); die("execl"); }
- 再修改exec.c读取参数作为写管道的文件描述符:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { if (argc < 2) exit(EXIT_FAILURE); int pipe_write_fd = atoi(argv[1]); char a = 'A'; write(pipe_write_fd, &a, sizeof(a)); close(pipe_write_fd); return 0; }
内容的提问来源于stack exchange,提问作者Yerni
相关产品推荐
相关产品推荐

