使用fork()在for循环中创建子进程,使用dup运行带有2个管道的execlp()

时间:2012-11-30 09:47:07

标签: c linux for-loop exec fork

我正在编写一个运行Linux命令的C程序,如:

  

$ cat / etc / passwd | cut -f1 -d:|排序

在等待孩子完成时,只有一个孩子成功终止。代码挂起显示“运行排序”

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>

int main()
{
  int i,fd1[2],fd2[2],status,listpid[3];
  pid_t child;
  pipe(fd1);
  pipe(fd2);

  for(i=0; i< 3; i++)
  {
    printf("\ncreating child\n");
    if((child = fork()) == -1)
    {
      perror("fork");
      exit(EXIT_FAILURE);

    }
    else if(child == 0)
    {
      if(i == 0)
      {
    close(1); dup(fd1[1]);
    close(fd1[0]);
    close(fd1[1]);
    printf("\nrunning cat /etc/passwd\n");
    fflush(stdout);
    execlp("cat","cat","/etc/passwd", (char *)NULL);
    exit(EXIT_SUCCESS);

      }
      else if(i == 1)
      {
    close(0); dup(fd1[0]);
    close(fd1[1]);
    close(fd1[0]);
    close(1); dup(fd2[1]);
    close(fd2[1]);
    close(fd2[0]);
    printf("\nrunning cut -f1 -d:\n");
    fflush(stdout);
    execlp("cut","cut","-f1","-d:", (char *)NULL);
    exit(EXIT_SUCCESS);

      }
      else if(i == 2)
      {
    close(0); dup(fd2[0]);
    close(fd2[1]);
    close(fd2[0]);
    close(fd1[0]);
close(fd1[1]);
    printf("\nrunning sort\n");
    fflush(stdout);
    execlp("sort","sort", (char *)NULL);
    exit(EXIT_SUCCESS);

      }

    }
    else
    {
      listpid[i]=child;
    }

  }

  close(fd1[0]);
  close(fd1[1]);
  close(fd2[0]);
  close(fd2[1]);

  for(i = 0; i < 2; i++) 
  {
    waitpid(listpid[i], &status, 0);

    if(WIFEXITED(status)) 
    {
      printf("\n[%d] TERMINATED (Status: %d)\n",listpid[i], WEXITSTATUS(status));

    }

  }
  exit(EXIT_SUCCESS);

}

2 个答案:

答案 0 :(得分:1)

它“挂起”的原因是因为sort正在等待更多输入。在输入管道关闭之前,它不会输出任何内容。您的管道可能有问题(您应该检查pipedup的返回值),但我看不到任何内容。

我的猜测是cut尚未退出。同样,最可能的原因是它的输入管道没有关闭。那么,它在哪里开放?

它不会在cat进程中打开,因为没有理由不退出。

它不会在父进程中打开,因为您已仔细关闭所有描述符。

它不会在cut进程中打开,因为你关闭了fd1的写入结束。

离开sort进程本身: 仍然打开fd1的描述符!

因此,sort挂起,因为它等待cut完成,cut挂起,因为它等待sort,即使sort也永远不会向fd1写入任何内容。

你应该关闭第三个孩子的fd1,或者你应该安排每个管子只存在于需要它们的孩子身上。

无论如何,那是我的理论。

答案 1 :(得分:0)

您需要关闭子级2中的管道fd1,否则子级1将等待更多可能的输入。

另一个问题是,您的waitpid循环应该有循环条件i < 3,而不是i < 2