我正在尝试在C中实现多管道,以运行像shell这样的多个命令。 我已经创建了一个链表(在我的代码中称为t_launch),如果你键入“ls | grep src | wc”,它就像这样:
wc - PIPE - grep src - PIPE - ls
每个PIPE节点都包含来自pipe()函数的int选项卡[2](当然,每个PIPE节点都有一个pipe()调用)
现在我正在尝试执行这些命令:
int execute_launch_list(t_shell *shell, t_launch *launchs)
{
pid_t pid;
int status;
int firstpid;
firstpid = 0;
while (launchs != NULL)
{
if ((pid = fork()) == -1)
return (my_error("Unable to fork\n"));
if (pid == 0)
{
if (launchs->prev != NULL)
{
close(1);
dup2(launchs->prev->pipefd[1], 1);
close(launchs->prev->pipefd[0]);
}
if (launchs->next != NULL)
{
close(0);
dup2(launchs->next->pipefd[0], 0);
close(launchs->next->pipefd[1]);
}
execve(launchs->cmdpath, launchs->words, shell->environ);
}
else if (firstpid == 0)
firstpid = pid;
launchs = launchs->next == NULL ? launchs->next : launchs->next->next;
}
waitpid(firstpid, &status, 0);
return (SUCCESS);
}
但这不起作用:看起来命令不会停止阅读。 例如,如果我输入“ls | grep src,”src“将从grep命令打印,但grep继续读取并且永不停止。如果我输入”ls | grep src | wc“,没有打印。我的代码有什么问题? 谢谢。
答案 0 :(得分:1)
如果我正确理解您的代码,您首先在shell进程中为每个PIPE调用pipe
。然后,您将继续fork
每个流程。
当您在child
进程中关闭每个子管道的未使用端时,此过程会遇到两个问题:
每个孩子都有管子,不会关闭那些不属于它的人
父(shell)进程打开所有管道。
因此,所有管道都是打开的,孩子们没有得到EOF。
顺便说一句,你需要为所有孩子wait()
,而不仅仅是最后一个孩子。考虑第一个孩子在关闭stdout
后进行一些长时间计算的情况,但请记住任何计算或stdout
关闭后的副作用,即使是短暂的,也可以在接收过程终止后进行排序,因为多处理基本上是非确定性的。