【发布时间】:2019-03-31 12:26:46
【问题描述】:
我正在尝试在 linux 中模拟终端的行为,用 c 代码构建一个 minishell,但是在尝试实现命令序列时遇到了问题,因为第一个命令的输出不会被正确接收由下一个通过管道。我们想要实现的方法是通过管道将第一个命令(child 1)的标准输出传递给第二个命令(child 2,在 child 1 死后出生),并将其用作第二个命令的标准输入。请注意,我在 for 循环的开头使用了 fork() 语句,因此每次迭代都会创建一个孩子,该孩子会在另一个孩子出生之前死亡。
我尝试使用 dup2 以外的其他命令,但没有任何效果。此外,当使用“ls | sort”之类的命令示例并截取第一个命令的输出时,第一个命令似乎返回已经排序的列表。
argvv 是一个 char *** 类型的变量,第一级中的每个命令都包含一个条目,第二级中每个命令的每个参数都包含一个条目
/*pipes have been created already; p1, p2 (p2 only useful for sequences of 3 commands)*/
for (command_counter = 0; command_counter < num_commands; command_counter++)
{
int chid = fork();
switch (chid)
{
case 0: // child
//COMMAND EXECUTION
/*Running commands with pipes */
/*Data is only ran through pipes if there's more than one command*/
/*we only implemented the version for two commands so far*/
/*...*/
if(num_commands==2)
{
/*Data is only ran through pipes if there's more than one command*/
if(command_counter==0)
{//The first command takes no input from pipe
close(p1[0]);
close(p2[0]);
close(p2[1]);
dup2(p1[1], 1);
close(p1[1]);
}
if(command_counter==1)
{ //Last command takes input only, output goes to stdout or output file
close(p2[1]);
close(p2[0]);
close(p1[1]);
dup2(p1[0], 0);
close(p1[0]);
}
}
execvp(argvv[command_counter][0], argvv[command_counter]);
case -1: // error
perror("Couldn't create child process\n");
exit(-1);
default:
// father
waitpid(chid, 0, 0);
}
}
close(p1[1]);
close(p1[0]);
close(p2[1]);
close(p2[0]);
我希望程序可以正常工作,但它只是在执行排序命令时停止。我很确定错误在于使用 dup2 进行第二次迭代,但我想确定我应该怎么做才能修复它
【问题讨论】:
-
"(孩子 2,在孩子 1 死后出生)" - 这不是管道的工作方式。所有部分同时运行。
-
我在 for 循环的开头使用了 fork() 语句,因此每次迭代都会创建一个子代,该子代会在另一个子代出生之前死亡。
-
是的,我的意思是错的。
-
如果第2个孩子还没有出生,则输出无处可去。