2010-02-03 118 views
9
#include<stdio.h> 
#include<unistd.h> 
#include<stdlib.h> 

int main(int argc,char **argv) 
{ 
    int fd[2]; 
    pid_t childpid; 
    pipe(fd); 
    childpid=fork(); 
    if (childpid == -1) 
    { 
     perror("Error forking..."); 
     exit(1); 
    } 
    if (childpid) /*parent proces*/ //grep .c 
    { 
     wait(&childpid);  //waits till the child send output to pipe 
     close(fd[1]); 
     close(0);  //stdin closed 
     dup2(fd[0],0); 
     execlp(argv[2],argv[2],argv[3],NULL); 

    } 
    if (childpid==0) //ls 
    { 
     close(fd[0]); /*Closes read side of pipe*/ 
     close(1);  //STDOUT closed 
     dup2(fd[1],1); 
     execl(argv[1],NULL); 
    } 
    return 0; 
} 

如果我将命令行参数设置为“ls grep .c”,我应该显示所有“.c”文件。使用C ..(使用叉)实现管道(“|”)

伪代码: - 我的子进程的运行“LS” &父进程将运行的“grep .c”的.. 父进程等待直到子进程结束,这样孩子写入管道。

试运行: -

bash-3.1$ ls | grep .c 
1.c 
hello.c 
bash-3.1$ ./a.out ls grep .c 
bash-3.1$ 

这是为什么发生?

+0

好的。我自己得到了答案。我在子进程中使用“execl()”,它不使用$ PATH环境变量搜索文件名.... 如果我更改为execlp(),则程序按预期运行。 – 2010-02-03 11:31:20

+2

你可能也不想那个“等(&childpid);” (或其不准确的评论)。它不会等到数据来自孩子,它会一直等到孩子进程状态发生变化 - 例如出口。如果您的子进程写入的不止是管道的数据(可能是8k),它将挂起等待父节点读取,而父节点仍然等待它退出。 – jmb 2010-02-03 12:04:37

+0

因此,我应该怎么做,让父母在孩子执行后执行......? – 2010-02-03 13:43:53

回答

8

一个简单的错误:您的execl调用实际上应该是execlp。此外,您可以摆脱waitclose陈述。然后你应该检查execlp的错误代码。

+0

+1在发布答案前1小时OP得到了自己的答案 – jschmier 2010-02-03 15:52:36

+0

您不需要测试'exec的返回状态*()'函数;如果函数返回,则失败。但是对于失败的'exec *()'函数应该有某种错误处理是正确的。 – 2013-07-22 18:37:06

1

还有一件事,close(0)close(1)是不必要的,dup2()函数自动为你做。

+0

你说得对。如果代码使用'dup()'而不是'dup2()',则'close(0)'和'close(1)'是相关的。 – 2013-07-22 18:39:07