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

时间:2014-10-06 01:30:54

标签: c shell exec pipe

我正在使用烟斗,叉子和叉子; exec实现用户shell。问题是它在某些情况下不起作用。例如,如果我有ls,它会起作用头但不会工作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
}

1 个答案:

答案 0 :(得分:1)

查看事件序列,ls | cat这就是现在发生的事情:

1)在父母中创建管道 2)生成ls个孩子 3)父母等待ls完成
4)生成cat个孩子 5)父母等待cat完成

正如您所注意到的那样,5)父母仍然打开了管道,因此cat永远不会完成。

当你在代码的父部分关闭它时它会被关闭...之前的3)。因此,当cat开始时,管道不再存在 - &gt;没有来自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个以上的命令,但是你明白了......

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