【问题标题】:Multi pipe in C (childs dont stop reading)C中的多管(孩子们不要停止阅读)
【发布时间】:2013-07-11 16:10:59
【问题描述】:

我正在尝试在 C 中实现多管道,以像 shell 一样运行多个命令。 我制作了一个链接列表(在我的代码中称为 t_launch),如果您键入“ls | grep src | wc”,它看起来像这样:

wc -- 管道 -- grep src -- 管道 -- ls

每个 PIPE 节点都包含一个来自 pipe() 函数的 int tab[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 源代码 | wc”,没有打印任何内容。我的代码有什么问题? 谢谢。

【问题讨论】:

  • 你能解释一下launchs = launchs->next == NULL ? launchs->next : launchs->next->next;吗?我错过了 sonethin 还是你跳过了每个第二个子进程?
  • 我跳过节点“PIPE”:链表看起来像“grep -- PIPE -- ls”,所以在我做了“grep stuff”之后,我转到“ls”,所以它是 - >next->next(单个 next 将把我带到管道节点上)
  • 谢谢我现在明白了。我猜 rici 是对的:客户端应该从 launch->prev 获取 stdin 并将 stdout 重定向到 launchs->next。 ...哎呀,他的评论被删除了,但是...
  • @IngoLeonhardt:我删除它是因为我看到列表的顺序是从右到左,所以next和prev是正确的。
  • @rici 我现在的失明已经痊愈了,顺便说一句。好的答案,算法,忘记我的最后评论,看看 rici 的答案

标签: c exec pipe dup2


【解决方案1】:

如果我正确理解您的代码,您首先在每个 PIPE 的 shell 进程中调用 pipe。然后你继续fork每个进程。

虽然您在child 进程中关闭了每个子管道的未使用端,但此过程存在两个问题:

  1. 每个孩子都有每个管道,不属于它的管道不会关闭

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

因此,所有管道都打开了,孩子们不会得到 EOF。

顺便说一句,您需要为所有孩子wait(),而不仅仅是最后一个。考虑第一个孩子在关闭stdout 后进行一些长时间计算的情况,但请记住,在关闭stdout 之后任何 计算或副作用,即使是很短的,也可以在sink 进程终止,因为多处理本质上是不确定的。

【讨论】:

  • 谢谢大家,我的实现真的很糟糕。我使用递归做了一个新代码,它工作得很好。再次感谢。
猜你喜欢
  • 2010-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多