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

如何获取exec()系列函数执行的外部程序的输出?

父进程获取exec执行命令输出的实现方法

核心思路

进程间通过管道实现输出传递:利用pipe()创建内核缓冲区构成的半双工通信通道,子进程将标准输出重定向到管道写端,父进程从管道读端读取数据即可拿到ls的执行结果。

具体实现步骤

  • 调用pipe()创建管道,得到读端、写端两个文件描述符
  • 调用fork()创建子进程
  • 子进程逻辑:
    • 关闭管道的读端(子进程不需要读操作)
    • 调用dup2()将STDOUT_FILENO(标准输出文件描述符)重定向到管道的写端
    • 执行execlp()启动ls命令,此时ls的所有输出都会写入管道而非终端
  • 父进程逻辑:
    • 关闭管道的写端(父进程不需要写操作)
    • 调用read()从管道读端循环读取数据,直到读完所有内容
    • 调用wait()回收子进程资源,避免产生僵尸进程

完整可运行示例代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#define BUF_SIZE 1024

int main(int argc, char ** argv) {
    int pipe_fd[2];
    // 先创建管道再fork
    if (pipe(pipe_fd) == -1) {
        perror("pipe创建失败");
        exit(EXIT_FAILURE);
    }

    int fid = fork();
    if(fid == -1) {
        perror("fork创建失败");
        exit(EXIT_FAILURE);
    }

    if(fid == 0) {
        // 子进程处理逻辑
        close(pipe_fd[0]); // 关闭不需要的读端
        // 把标准输出重定向到管道写端
        if (dup2(pipe_fd[1], STDOUT_FILENO) == -1) {
            perror("输出重定向失败");
            exit(EXIT_FAILURE);
        }
        close(pipe_fd[1]); // 重定向完成后关闭原写端
        execlp("ls", "ls", NULL);
        // execlp只有执行失败才会走到下行
        perror("execlp执行失败");
        exit(EXIT_FAILURE);
    } else {
        // 父进程处理逻辑
        close(pipe_fd[1]); // 关闭不需要的写端
        char buf[BUF_SIZE];
        ssize_t read_len;
        printf("获取到的ls输出如下:\n");
        // 循环读取管道内容
        while ((read_len = read(pipe_fd[0], buf, BUF_SIZE - 1)) > 0) {
            buf[read_len] = '\0';
            printf("%s", buf);
        }
        close(pipe_fd[0]);

        // 回收子进程
        int status;
        wait(&status);
    }
    return 0;
}

注意事项

  • 必须在fork()之前调用pipe()创建管道,否则父子进程无法拿到同一个管道的文件描述符
  • 父子进程都要主动关闭自己不需要的管道端,否则父进程的read()会因为管道写端没有完全关闭而永久阻塞
  • dup2()执行成功后会自动关闭第二个参数对应的旧文件描述符,原管道写端仍建议手动关闭避免资源泄漏

内容的提问来源于stack exchange,提问作者bence

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:06:03