You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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调用前关闭该描述符:

  1. 先修改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");
}
  1. 再修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 12:36:03