0

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

$ 猫 /etc/passwd | 切-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);

}
4

2 回答 2

1

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

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

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

它不会在父进程中打开,因为您已经小心地关闭了所有描述符。

在这个过程中它不会打开,cut因为你关闭了 fd1 的写端。

这留下了sort进程本身:仍然打开了 fd1 的描述符!

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

您应该在第三个孩子中关闭 fd1,或者您应该安排每个管道仅存在于需要它们的孩子中。

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

于 2012-11-30T10:06:22.600 回答
0

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

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

于 2012-11-30T10:00:25.507 回答