LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 681|回复: 3

问大家一个管道的问题

[复制链接]
发表于 2006-3-10 17:00:02 | 显示全部楼层 |阅读模式
写一个通用的程序pipe,它使用两个程序的名字作为参数,例如pipe who sort     pipe ls sort等,程序的逻辑如下所示:
                                                
      child                                                
                                                   
     close(p[0])                              
     dup2(p[1],1)                           
     close(p[1])                             
     exec "ls"

      parent

    close(p[1])
    dup2(p[0],0)
    close(p[0])
    exec "sort"
我不明白为什么在子进程中要先关闭p[0],在父进程中要先关闭p[1],有的书上说不用的管道描述符关掉不会出错,但是我不明白不关掉会不会出现其他问题,关闭不用的管道描述符还有没有其他原因,恳请各位高手指教!下面是程序的代码,在源程序中我把子进程中的close(p[0])和父进程中的close(p[1])注释掉了,程序运行出现了问题,达不到所要求的目的,不知道为什么会出现这样的错误,还请高手分析一下原因,多谢了!
#include        <stdio.h>
#include        <unistd.h>
#define oops(m,x)       { perror(m); exit(x); }
main(int ac, char **av)
{
        int     thepipe[2],                     /* two file descriptors */
                newfd,                          /* useful for pipes     */
                pid;                            /* and the pid          */
        if ( ac != 3 ){
                fprintf(stderr, "usage: pipe cmd1 cmd2\n");
                exit(1);
        }
        if ( pipe( thepipe ) == -1 )            /* get a pipe           */
                oops("Cannot get a pipe", 1);
        /*      now we have a pipe, now let's get two processes         */
                                                                                                                                               
        if ( (pid = fork()) == -1 )                     /* get a proc   */
                oops("Cannot fork", 2);
                                                                                                                                               
        /*      Right Here, there are two processes                     */
        /*             parent will read from pipe                       */
                                                                                                                                               
        if ( pid > 0 ){                 /* parent will exec av[2]       */
                //close(thepipe[1]);    /* parent doesn't write to pipe */
                                                                                                                                               
                if ( dup2(thepipe[0], 0) == -1 )
                        oops("could not redirect stdin",3);
                                                                                                                                               
                close(thepipe[0]);      /* stdin is duped, close pipe   */
                //close(0);
                execlp( av[2], av[2], NULL);
                oops(av[2], 4);
        }
                                                                                                                                               
        /*       child execs av[1] and writes into pipe                 */
                                                                                                                                               
        //close(thepipe[0]);            /* child doesn't read from pipe */
                                                                                                                                               
        if ( dup2(thepipe[1], 1) == -1 )
                oops("could not redirect stdout", 4);
                                                                                                                                               
        close(thepipe[1]);              /* stdout is duped, close pipe  */
        //close(1);
        execlp( av[1], av[1], NULL);
        oops(av[1], 5);
}
发表于 2006-3-10 18:54:09 | 显示全部楼层
把代码用 [code] [/code] 包住
也可以用[php] [/php]
回复 支持 反对

使用道具 举报

发表于 2006-3-10 22:56:46 | 显示全部楼层
与 p[1] 相关的所有句柄都关掉时才能让 sort 从 p[0] 中读到eof.
主程序先关 p[1]就是为了保证ls 退出时关掉的标准输出是 p[1]的最后一个dup
回复 支持 反对

使用道具 举报

发表于 2006-3-12 22:01:10 | 显示全部楼层
你现要明白fork()的意义,在fork()后,子进程会复制父进程的一切(比如书局空间堆和栈等).
现在来看pipe(thepipe),这相当于在当前进程(即父进程)创建了管道,注意是创建了2个管道fd[0]和
fd[1],其中fd[0]是读管道,fd[1]是写管道,在fork()后那,子进程复制了父进程的一切,这样子进程也 有了fd[0]和fd[1]管道,这样父进程的fd[1]便连着父进程的fd[0]和子进程的fd[0],所以当父进程写东西时,它会流向父进程的fd[0]或子进程的fd[0],也就是说不一定流向子进程的fd[0],程序当然会出错了,所以必须关掉父进程的fd[0],这样当父进程写东西时它只会流向子进程的fd[0].
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表