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

子进程无法获取父进程写入stdin的输入,execl调用test1异常

问题根源与解决方案

哦,这问题其实很直白——你搞混了命令行参数和**标准输入(stdin)**的区别!

为什么sort能工作,test1不行?

先看你的test1.c代码:它从头到尾都是在遍历argv(命令行参数数组)来打印内容,根本没有调用任何读取stdin的函数(比如fgets、scanf)。而sort命令的设计就是从stdin读取数据进行排序,所以你用管道把数据传到它的stdin,它能正常处理。但test1根本不关心stdin里有什么,它只认启动时传入的命令行参数。

两种解决思路

思路1:修改test1,让它从stdin读取数据

如果你希望test1能接收管道传来的数据,需要修改它的逻辑,让它读取stdin的内容。比如改成这样:

#include<stdio.h>
#include<stdlib.h>
int main(int argc, char** argv){
    printf("hello!\n");
    // 保留原有逻辑:打印命令行参数
    for(int i = 0; i < argc; i++){
        printf("%s\n", argv[i]);
    }
    // 新增:读取stdin的每一行并打印
    char buf[1024];
    while(fgets(buf, sizeof(buf), stdin) != NULL){
        printf("%s", buf); // fgets已经包含换行符,无需额外添加\n
    }
    return 0;
}

修改后运行./example,输出会符合预期:

hello!
test1
pear
peach
apple

思路2:不修改test1,直接传递命令行参数

如果你想保持test1的原有逻辑,那就要在启动test1时把那些单词作为命令行参数传进去,就像你手动运行./test1 pear peach apple一样。这里用execvp会比execl更灵活(适配可变数量的参数):
修改example.c的子进程部分:

if (pid == 0) { // 子进程分支
    // 不需要管道,直接传命令行参数
    close(fds[0]); 
    close(fds[1]);
    // 构造参数数组,最后一个元素必须为NULL
    char *args[] = {"test1", "pear", "peach", "apple", (char*)0};
    if (execvp("./test1", args) < 0) exit(0);
}

同时父进程的管道相关代码可以全部删除(因为不需要再通过管道传数据),修改后的父进程部分:

// 父进程分支
int status;
pid_t wpid = waitpid(pid, &status, 0); // 等待子进程结束
return wpid == pid && WIFEXITED(status) ? WEXITSTATUS(status) : -1;

这样运行./example的输出就和直接执行./test1 pear peach apple完全一致:

hello!
./test1
pear
peach
apple

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:23:37