子进程无法获取父进程写入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
相关产品推荐
相关产品推荐

