c中的pipe()和fork()

我需要创建两个子进程。 一个孩子需要运行命令“ls -al”并将其输出重定向到下一个子进程的输入,然后该进程将对其输入数据运行命令“sort -r -n -k 5”。 最后,父进程需要读取(已经排序的数据)并将其显示在终端中。 终端中的最终结果(执行程序时)应该与我直接在shell中输入以下命令相同:“ls -al | sort -r -n -k 5”。 为此,我需要使用以下方法:pipe(),fork(),execlp()。

我的程序编译,但我没有得到所需的输出到终端。 我不知道出了什么问题。 这是代码:

#include  #include  #include  #include  int main() { int fd[2]; pid_t ls_pid, sort_pid; char buff[1000]; /* create the pipe */ if (pipe(fd) == -1) { fprintf(stderr, "Pipe failed"); return 1; } /* create child 2 first */ sort_pid = fork(); if (sort_pid  0) { // parent process wait(NULL); // wait for children termination /* create child 1 */ ls_pid = fork(); if (ls_pid < 0) { // error creating Child 1 process fprintf(stderr, "\nChild 1 Fork failed"); return 1; } else if (ls_pid == 0) { // child 1 process close(1); // close stdout dup2(fd[1], 1); // make stdout same as fd[1] close(fd[0]); // we don't need this end of pipe execlp("bin/ls", "ls", "-al", NULL);// executes ls command } wait(NULL); read(fd[0], buff, 1000); // parent reads data printf(buff); // parent prints data to terminal } else if (sort_pid == 0) { // child 2 process close(0); // close stdin dup2(fd[0], 0); // make stdin same as fd[0] close(fd[1]); // we don't need this end of pipe execlp("bin/sort", "sort", "-r", "-n", "-k", "5", NULL); // executes sort operation } return 0; } 

您的父进程在创建ls进程之前wait排序进程完成。

排序过程需要在完成之前读取其输入。 它的输入来自ls,直到wait之后才会开始。 僵局。

您需要创建两个进程,然后wait它们。

此外,您的文件描述符操作不太正确。 在这对电话中:

 close(0); dup2(fd[0], 0); 

关闭是多余的,因为如果存在,dup2将自动关闭现有的fd 0。 您应该在dup2之后close(fd[0]) ,因此您只有一个文件描述符绑定到管道的那一端。 如果你想要非常健壮,你应该测试枯萎fd[0]==0 ,在那种情况下跳过dup2并关闭。

将所有这些应用到其他dup2也。

然后是打开管道的父进程的问题。 在你把它们传递给孩子们之后,我会说你应该关闭父母管道的两端,但是在最后一次wait之后你从fd[0]那里得到了一些奇怪的东西…我不知道为什么就在那里。 如果ls|sort管道已正确运行,则管道将在之后为空,因此无需读取任何内容。 在任何情况下,您肯定需要在父级中关闭fd[1] ,否则排序过程将无法完成,因为在所有编写器关闭之前管道不会指示EOF。

奇怪的read是一个可能会崩溃的printf ,因为读取缓冲区不会被'\0'终止。

使用execlp的关键在于它为您执行$PATH查找,因此您不必指定/bin/ 。 我的第一次测试运行失败,因为我的排序在/usr/bin/ 。 为什么不需要硬编码路径?