2011-12-19 45 views
4

任何人都可以告诉我这段代码有什么问题吗?叉执行管重定向问题

总之,它创建输入和输出管道和fork-exec的sort程序。父母读取字典/usr/share/dict/words,并将其写入dup2()'d到sort的管道中,并同样从中读取输出,并将其打印到终端(父母的标准输出)。或者至少,这就是应该发生的事情。

回溯表示父母挂在130行的read()(标记为'XXX'注释)。这几乎就好像sort不知道文件结束,但关闭pipeIn的写入结束应该'发出'这个信号,对吗?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h> 

int main(int argc, char** argv) 
{ 
    int pipeIn[2]; 
    int pipeOut[2]; 

    if ((pipe(pipeIn)) == -1) 
    { 
     perror("pipe"); 
     exit(EXIT_FAILURE); 
    } 

    if ((pipe(pipeOut)) == -1) 
    { 
     perror("pipe"); 
     exit(EXIT_FAILURE); 
    } 

    pid_t child = fork(); 

    if (child == 0) 
    { 
     // This is child! 

     if ((dup2(pipeIn[0], STDIN_FILENO)) == -1) 
     { 
      perror("dup2"); 
      exit(EXIT_FAILURE); 
     } 

     if ((dup2(pipeOut[1], STDOUT_FILENO)) == -1) 
     { 
      perror("dup2"); 
      exit(EXIT_FAILURE); 
     } 

     if ((dup2(pipeOut[1], STDERR_FILENO)) == -1) 
     { 
      perror("dup2"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeIn[0])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeOut[1])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     if ((execlp("sort", "-r", NULL)) == -1) 
     { 
      perror("execlp"); 
      exit(EXIT_FAILURE); 
     } 
    } 
    else if (child == -1) 
    { 
     perror("fork"); 
     exit(EXIT_FAILURE); 
    } 
    else 
    { 
     // This is parent! 

     if ((close(pipeIn[0])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeOut[1])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     int dict = open("/usr/share/dict/words", O_RDONLY); 

     if (dict == -1) 
     { 
      perror("open"); 
      exit(EXIT_FAILURE); 
     } 

     char buf[1024]; 
     int count; 

     while ((count = read(dict, buf, sizeof(char) * 1024)) > 0) 
     { 
      putchar('.'); 

      if ((write(pipeIn[1], buf, count)) == -1) 
      { 
       perror("write 1"); 
       exit(EXIT_FAILURE); 
      } 
     } 

     if (count == -1) 
     { 
      perror("read"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(dict)) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeIn[1])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     while ((count = read(pipeOut[0], buf, sizeof(char) * 1024)) > 0) // XXX 
     { 
      putchar('!'); 

      if ((write(STDOUT_FILENO, buf, count)) == -1) 
      { 
       perror("write 2"); 
       exit(EXIT_FAILURE); 
      } 
     } 

     if (count == -1) 
     { 
      perror("read"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeOut[0])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 
    } 

    return EXIT_SUCCESS; 
} 

谢谢你的任何意见(赦免双关语)。

+0

可能重复之前的某处添加以下代码://计算器。问题/ 916900 /有trouble-with-fork-pipe-dup2和exec-in-c) – wallyk 2011-12-19 00:14:31

+0

我已经阅读过,看起来相当不同。 – Doddy 2011-12-19 00:16:48

+0

我同意 - 交叉引用的问题有所不同。 – 2011-12-19 03:37:27

回答

2

您的问题是,您没有关闭智利进程中管道未使用的末端。所以,你需要[用C具有与叉(),管(),DUP2()的麻烦和exec()](HTTP的exec

if ((close(pipeIn[1])) == -1) 
    { 
     perror("close"); 
     exit(EXIT_FAILURE); 
    } 

    if ((close(pipeOut[0])) == -1) 
    { 
     perror("close"); 
     exit(EXIT_FAILURE); 
    } 
+0

+1 - 你说得对。这是违反直觉的,但是如果你在一个子进程中使用一个管道作为标准输入或者标准输出,那么你通常最终会关闭由'pipe()'返回的两个文件描述符**。 – 2011-12-19 03:36:01

+0

是的,我一开始并没有得到它,但现在我想到了它(我直到今天从来没有这样想过)。在fork之后,实际上有两个可以写入管道的开放文件描述符。因此,在读取管道时,无法读取'eof',直到写入结束的所有文件描述符都被关闭。 – Sodved 2011-12-19 05:49:22

+0

谢谢,它正在工作,但它不是按相反顺序打印单词列表。 'execlp(“sort”,“-r”,NULL)的语法是错误的吗? – Doddy 2011-12-19 14:22:44