2016-11-07 109 views
1

我还不熟悉进程,管道和dup2,因此我希望有人能帮我弄清楚我创建的程序有什么问题。这个程序应该运行ls | wc。到目前为止输出我得到的是:使用进程通过管道运行命令

wc : standard input : Bad file descriptor 
     0   0   0 
ls : write error : Bad file descriptor 

后,我得到这个输出,终端仍然接受输入。这就像wc仍然在运行,尽管如果我先放置类似ls的命令(之前没有任何其他输入),它将运行它们并关闭。我试着在/之前/之后运行ps,并且程序仍在运行,并且没有显示任何打开bash和ps的进程。 (我运行此程序在Linux终端)

这里是我的代码:

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

int main(int argc, char* argv[]){ 
     pid_t pid; 
     int fd[2]; 
     char com1[1024] = ("ls"); 
     char com2[1024] = ("wc"); 
     pipe(fd); 
     pid = fork(); 
     if(pid == 0){ 
      open(fd[1]); 
      dup2(fd[0],STDOUT_FILENO); 
      close(fd[0]); 
      execlp(com1, com1, NULL); 
        } 
     else { 
      pid = fork(); 
      if (pid == 0){ 
        open(fd[0]); 
        dup2(fd[1],STDIN_FILENO); 
        close(fd[1]); 
        execlp(com2, com2, NULL); 
         } 
      } 
return 0; 
} 

记住,我一定知道,如果需要检查命令(如if(pid<0)exit(0);),但我想简化我的代码尽可能多地查看是否由于粗心导致任何错误。 提前谢谢!

+0

这是否代码甚至编译?它至少应该使编译器对你发出警告。调用'open(fd [0])'(当然'open(fd [1])')是无效的,应该删除。 –

+0

至于你的问题,我建议你阅读[管'手册页](http://man7.org/linux/man-pages/man2/pipe.2.html)。请密切注意哪些描述符是管道的读取和写入结束。 –

+0

此代码编译没有任何错误到目前为止,我删除了open()命令,并得到相同的输出 –

回答

0

根据the pipe manual page

pipefd[0]指管的读端。 pipefd[1]指的是管道的写入结束。

现在从第一个孩子这一行,调用ls命令的过程:

dup2(fd[0],STDOUT_FILENO); 

在这里,您复制阅读管结束STDOUT_FILENO,即,其中输出写入。如果你停下来思考一下,你会如何写入一个只读的文件描述符如fd[0]

与其他子进程相同,你在这里编写写入管道标准输入结束。

解决方法很简单:交换重复描述符的位置。第一个子进程使用fd[1],第二个子进程使用fd[0]

在调用ls命令的第一过程:

dup2(fd[1],STDOUT_FILENO); 
close(fd[1]); 
execlp(com1, com1, NULL); 

而在第二个孩子的过程,其中调用wc命令:

dup2(fd[0],STDIN_FILENO); 
close(fd[0]); 
execlp(com2, com2, NULL);