c - 在某些情况下,在管道中执行第二个/最后一个命令后进程挂起

标签 c shell exec pipe

我正在使用 pipe、fork 和 exec 来实现用户 shell。问题是它在某些情况下不起作用。例如,如果我有 ls | 它会起作用head 但不适用于 ls |猫。它将显示 cat 的输出,但之后会挂起而不会返回到提示符。

关于代码,我将输入存储在 c->args[0] 中,为此我派生了一个子节点并执行它。

我知道第二个 exec 仍在等待 EOF,但在此之前关闭文件描述符没有帮助。

经历类似的问题,我也尝试在等待之前关闭父进程中的文件描述符,但在这样做之后甚至 ls |头不工作。 我已经在下面发布了相关功能。

    void executeProcess(Cmd c,int noofcmds)
{
//    printf("Will be entering fork procedure \n");
     int cmdNo;
     pipe(fd);
  for (cmdNo = 0;cmdNo < noofcmds; cmdNo ++)
  { 

    int processid = fork();
    pid_t childpid;
//    printf("Process id %d\n",processid);
    if (processid == 0)
      { 
//  if (noofcmds != 1)
//       {  
    if (cmdNo == 0)
     {
       printf("Inside first child \n");
       close(fd[0]);
       dup2(fd[1], 1);
//     close(fd[0]); 
     } else if (cmdNo == noofcmds-1)
     {  
       close(fd[1]);
       dup2(fd[0], 0);
//         close(fd[0]);

     }
//  close(fd[1]);
//  close(fd[0]);
        if (execvp(c->args[0],c->args) < 1)
     { printf("Error\n");
     }
      } else 
      {
//  printf("Waiting in parent\n");
//  close(fd[0]);
//  close(fd[1]);

    int status;
    int returnedpid;
    wait(&status);
        printf("Returned after waiting\n");
//  close(fd[0]);
//  close(fd[1]);   
      }
    c = c->next;
//  close(fd[0]);
//  close(fd[1]);
  } // end of for
}

最佳答案

查看事件顺序,使用 ls | cat 这是现在发生的事情:

1) 管道在父级中创建。
2) ls child 被生成
3) parent 等待 ls 完成
4) cat child 被生成
5) parent 等待 cat 完成

如您所见,在 5) 中,父级仍然打开管道,因此 cat 永远不会完成。

当您在代码的父部分关闭它时,它会在 3) 之前关闭...因此,当 cat 启动时,管道不再存在 -> cat 没有输出。

你需要的是在 4) 之后用类似的东西关闭它:

...
else  // in parent
{
    // printf("Waiting in parent\n");

    if (cmdNo == 1)  // second child is spawned, can close the pipe now.
    {
        close(fd[0]);
        close(fd[1]);
    }

    int status;
    wait(&status);
    printf("Returned after waiting\n");
}

代码将需要更多的工作来处理一个管道中的 2 个以上的命令,但你明白了......

提示:找一个自动缩进代码的编辑器,它会让你的生活更轻松!

关于c - 在某些情况下,在管道中执行第二个/最后一个命令后进程挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26208975/

相关文章:

c - 获取位域中唯一位的数量

c - tweenacl api 和不同的 key 对

java - 从 Shell 脚本进行通信的最有效方法 -> 运行 Java APP

php - 如何从 Action 中在后台正确运行 Symfony 任务?

c - pthread_join 参数类型错误

c - 在C中手动将4位int(十进制)提取到字符串中

python - 记录循环脚本的开始和结束时间

java - 将带有空格分隔符的字符串转换为数组。并像字符串一样输出这个数组

c - 使用流在 *nix 进程之间传输输入/输出

linux - linux-execve : On executing ls command - get error "ls: cannot access/etc : No such file or directory"