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

C语言如何在fork创建的子进程中获取并打印exec()执行输出

问题说明

你当前代码存在两个核心问题:

  • execlp 传参错误:exec族函数的参数列表中,第一个可变参数必须对应被执行程序的argv[0](惯例为程序自身名称),你漏传了date作为首个参数,导致date命令无法识别+%H:%M:%S格式参数,执行会直接失败。
  • exec类函数的核心逻辑是用新程序的映像完全替换当前进程的地址空间,一旦exec调用成功,当前进程原有代码会全部消失,直接运行新程序,根本不可能在原有子进程的代码逻辑中捕获exec后程序的输出。如果需要在子进程内获取被执行命令的输出内容再自定义打印,不能直接在子进程中调用exec,需要通过管道重定向被执行程序的标准输出,再读取输出内容。
    另外你的父进程没有回收子进程资源,运行时会产生僵尸进程。
实现方案

如果你的需求只是让子进程执行date命令并输出时间,不需要自定义处理输出内容,只需要修正execlp的参数,同时在父进程中回收子进程即可。
如果需要在子进程内部获取命令的输出内容,自行完成打印后再退出,推荐两种实现方式:

方式1:使用popen快速实现(最简便)

popen是标准库封装好的函数,会自动完成管道创建、子进程fork、程序exec、输出重定向的全流程,你只需要读取返回的文件流就能拿到命令输出。
修正后的完整代码如下:

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

int main()
{
    time_t endwait;
    time_t start = time(NULL);
    time_t seconds = 60;
    endwait = start + seconds;

    while (start < endwait)
    {
        pid_t pid = fork();
        if(pid == 0){
            // 子进程逻辑:用popen执行date命令,读取输出
            FILE *fp = popen("date +%H:%M:%S", "r");
            if (fp == NULL) {
                perror("popen failed");
                _exit(1);
            }
            char buf[64] = {0};
            // 读取命令输出
            if (fgets(buf, sizeof(buf), fp) != NULL) {
                printf("子进程获取到exec执行结果:%s", buf);
            }
            pclose(fp);
            _exit(0); // 打印完成后终止子进程
        }
        // 父进程回收子进程资源,避免僵尸进程
        waitpid(pid, NULL, 0);
        sleep(5);
        start = time(NULL);
    }

    printf("end time is %s", ctime(&endwait));
    return 0;
}

方式2:手动创建管道实现(便于理解原理)

如果要手动实现逻辑,需要在子进程中创建管道,再fork孙进程执行date命令,将孙进程的标准输出重定向到管道写端,子进程从管道读端读取输出内容即可:

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

int main()
{
    time_t endwait;
    time_t start = time(NULL);
    time_t seconds = 60;
    endwait = start + seconds;

    while (start < endwait)
    {
        pid_t pid = fork();
        if(pid == 0){
            int pipe_fd[2];
            if (pipe(pipe_fd) == -1) {
                perror("pipe create failed");
                _exit(1);
            }
            pid_t grand_pid = fork();
            if (grand_pid == 0) {
                // 孙进程:关闭读端,重定向stdout到管道写端,执行date
                close(pipe_fd[0]);
                dup2(pipe_fd[1], STDOUT_FILENO);
                close(pipe_fd[1]);
                execlp("date", "date", "+%H:%M:%S", NULL);
                _exit(1);
            }
            // 子进程:关闭写端,读取管道内容
            close(pipe_fd[1]);
            char buf[64] = {0};
            read(pipe_fd[0], buf, sizeof(buf)-1);
            close(pipe_fd[0]);
            // 回收孙进程
            waitpid(grand_pid, NULL, 0);
            printf("子进程获取到exec执行结果:%s", buf);
            _exit(0);
        }
        waitpid(pid, NULL, 0);
        sleep(5);
        start = time(NULL);
    }

    printf("end time is %s", ctime(&endwait));
    return 0;
}
补充说明

如果你不需要在子进程代码中额外处理输出,只是要date命令自己打印结果,那子进程里的逻辑可以简化为修正参数的execlp调用即可,不需要管道:

if(pid == 0){
    // 注意第二个参数是argv[0],传"date"
    execlp("date", "date", "+%H:%M:%S", NULL);
    // exec只有失败才会走到这里
    perror("execlp failed");
    _exit(1);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 19:54:20