fork / pipe /以递归函数关闭

时间:2016-06-01 17:08:06

标签: c unix recursion pipe dup2

为了实现shell命令解释器,我尝试执行管道。 要做到这一点,我使用递归函数,我使用管道函数和一些重定向与dup2。 这是我的代码:

void            test_recurs(pid_t pid, char **ae)
{
  char  *const  arg[2] = {"/bin/ls", NULL};
  char  *const  arg2[3] = {"/bin/wc", NULL};
  static int    limit = 0;
  int           check;
  int           fd[2];

  if (limit > 5)
    return ;
  if (pipe(fd) == -1)
    {
      printf("pipe failed\n");
      return ;
    }
  pid = fork();
  if(pid != 0)
    {
      printf("père %d\n",getpid());
      close(fd[0]);
      dup2(fd[1], 1);
      close(fd[1]);
      if ((execve("/bin/ls", arg, ae)) == -1)
        exit(125);
      dprintf(2, "execution ls\n");
      wait(&check);
    }
  else
    {
      printf("fils %d\n", getpid());
      close(fd[1]);
      dup2(fd[0], 0);
      close(fd[0]);
      if ((execve("/bin/wc", arg2, ae)) == -1)
        printf("echec execve\n");;
      dprintf(2, "limit[%d]\n", limit);
      limit++;
      test_recurs(pid, ae);
    }
}

问题是它只执行一次“ls | wc”然后等待标准输入。我知道问题可能来自管道(和重定向)。

1 个答案:

答案 0 :(得分:2)

有点不清楚你是如何尝试使用你所提供的功能的,但这里有一些值得注意的一点:

  • 依靠静态变量限制递归深度是不好的形式,因为它不是线程安全的,因为你需要做额外的工作来管理它(例如,确保当函数返回时,任何更改都会被撤消)。请改用函数参数。

  • 正如在注释中所观察到的,exec-family函数仅在失败时返回。虽然你承认这一点,但我不确定你是否理解后果,因为你的fork的两个分支都包含永远不会被执行的代码。特别是递归调用已经死了,永远不会被执行。

  • 此外,调用函数的过程本身会执行execve()调用。函数未返回的原因是它将进程映像替换为新进程的。这意味着函数test_recurs() 不会返回。

正如shell通常必须fork / exec来启动单个外部命令一样,它通常必须fork / exec来管道中的每个命令。如果它没有这样做,那么之后它就不再运行了 - 无论它执行什么,而不是分叉运行。

  

问题是它只执行" ls | WC"一次然后等待标准输入。

当然它没有递归,因为递归调用是在一段死代码中。我怀疑你错误地认为它后来等待标准输入,因为调用该函数的进程执行/bin/ls,它不从标准输入读取。然而,当ls退出时,既没有shell也没有ls,那么你看到的东西似乎是在stdin上等待。