使用dup2重新匹配手动管道的无法解释的行为

时间:2012-09-13 21:51:03

标签: linux posix pipe systems-programming dup2

我有两组代码都试图执行像ls|grep pip这样的代码 一个有效,一个无效。

工作代码创建了2个子进程,并使用一个子进行execlp一个命令,另一个只是尝试通过创建一个子进行。即执行ls说孩子和父母的grep。这似乎不起作用。我似乎也没有任何错误。

有人可以告诉我这是什么问题吗?为什么它存在?

不工作:

void runpipe()
{
    pid_t childpid;
    int fd[2];
    pipe(fd);
    int saved_stdout;
    int saved_stdin;
    saved_stdout=dup(STDOUT_FILENO);
    saved_stdin=dup(STDIN_FILENO);
    if((childpid=fork())==0)
    {
            dup2(fd[WRITE_END],STDOUT_FILENO);
            close(fd[WRITE_END]);
            execlp("/bin/ls","ls command","-l",NULL);

            dup2(STDOUT_FILENO,fd[1]);
            _exit(0);
    }
    else if(childpid>0)
    {

            dup2(saved_stdout,STDOUT_FILENO);
            dup2(fd[READ_END],STDIN_FILENO);
            close(fd[READ_END]);
            execlp("/bin/grep","grep","pip",NULL);
            wait();
            _exit(0);

    }
    else
    {
            printf("ERROR!\n");
    }
}

void runpipe() { pid_t childpid; int fd[2]; pipe(fd); int saved_stdout; int saved_stdin; saved_stdout=dup(STDOUT_FILENO); saved_stdin=dup(STDIN_FILENO); if((childpid=fork())==0) { dup2(fd[WRITE_END],STDOUT_FILENO); close(fd[WRITE_END]); execlp("/bin/ls","ls command","-l",NULL); dup2(STDOUT_FILENO,fd[1]); _exit(0); } else if(childpid>0) { dup2(saved_stdout,STDOUT_FILENO); dup2(fd[READ_END],STDIN_FILENO); close(fd[READ_END]); execlp("/bin/grep","grep","pip",NULL); wait(); _exit(0); } else { printf("ERROR!\n"); } }

以下是代码:

工作:

    int runpipe(){
    pid_t pid;
    int fd[2];

    pipe(fd);
    int i;
    pid=fork();

    if (pid==0) {

            printf("i'm the child used for ls \n");
            dup2(fd[WRITE_END], STDOUT_FILENO);
            close(fd[READ_END]);
            execlp("ls", "ls", "-al", NULL);
            _exit(0);
    } else {
            pid=fork();

            if (pid==0) {
                    printf("i'm in the second child, which will be used to grep\n");
                    dup2(fd[READ_END], STDIN_FILENO);
                    close(fd[WRITE_END]);
                    execlp("grep", "grep","pip",NULL);
            }
            else wait();
    }
    return 0;
}

1 个答案:

答案 0 :(得分:0)

父级需要在执行grep之前关闭管道的写入端。出于某种原因,具有两个子节点的代码会关闭该文件描述符,但不会在只有一个子节点的代码中关闭。您将打开几个描述符,但管道上的写入方面是重要的。在管道写入侧的所有副本都关闭之前,读取器(exec'd grep)将无法完成。由于没有关闭它,grep是一个保持打开的那个,所以grep永远不会终止,只是等待更多的数据。