2013-07-11 27 views
0

我想在C中实现多管道,以运行多个命令,如壳。 我已经做了链接列表(在我的代码称为t_launch),它看起来像,如果你键入 “ls | grep的SRC |厕所”:多管道C(孩子们不要停止阅读)

厕所 - 管 - grep的SRC - 管 - LS

每个PIPE节点包含一个int标签[2]从管道()函数(当然,也出现了一个管()调用为每个管道节点)

现在我试图执行这些命令:

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

你能解释'launchs = launchs-> next == NULL吗? launchs-> next:launchs-> next-> next;'请吗?我是否错过了sonethin,或者你跳过每一个第二个孩子的过程? –

+0

我跳过节点“PIPE”:链接列表看起来像“grep - PIPE - ls”,所以在我做了“grep stuff”之后,我去了“ls”,所以它是 - > next-> next(a单下一个会让我在管道节点上) – Algo

+0

谢谢我现在明白了。我猜rici是正确的:客户端应该从'launch-> prev'获得'stdin'并将'stdout'重定向到'launchs-> next'。 ... oops,他的评论ist删除,但仍然... –

回答

1

如果我正确地理解你的代码,你第一个电话pipe在每一个管壳的过程,你再继续fork每个进程。

当你这样做关闭每个孩子的管道中未使用的结束在child过程,这个过程存在两个问题:

  1. 每个孩子都有逢钢管,不关闭那些其别t属于它

  2. 父(shell)进程打开所有管道。

因此,所有的管道都是开放的,而孩子们不会得到EOF。

顺便说一句,您需要wait()为所有的孩子,而不仅仅是最后一个。考虑第一个孩子在关闭stdout之后做了一些长计算的情况,但请记住stdoutstdout关闭之后计算或副作用,即使是短的,在宿进程终止之后可以排序,因为多处理本质上是非线性的,确定性。

+0

谢谢大家,我的执行情况非常糟糕。 我做了一个使用递归的新代码,它完美地工作。再次感谢。 – Algo