如何获取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
相关产品推荐
相关产品推荐

