【问题标题】:Unexplainable behaviour with replecating manual piping using dup2使用 dup2 复制手动管道时出现无法解释的行为
【发布时间】:2012-09-13 21:51:02
【问题描述】:

我有两组代码都试图执行类似ls|grep pip 一种有效,一种无效。

工作代码创建了 2 个子进程,每个子进程使用一个子进程来执行一个命令,而另一个只是尝试通过创建一个子进程来执行此操作。即执行 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");
    }
}

代码如下:

工作:

    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;
}

【问题讨论】:

    标签: linux posix pipe systems-programming dup2


    【解决方案1】:

    在执行 grep 之前,父级需要关闭管道的写入端。出于某种原因,您的具有两个孩子的代码会关闭该文件描述符,但不会在只有一个孩子的代码中。您将打开几个描述符,但管道上的写入端是重要的。读取器(exec'd grep)将在管道写入端的所有副本都关闭之前完成。如果未能关闭它,则 grep 将使其保持打开状态,因此 grep 永远不会终止,而只是等待更多数据。

    【讨论】:

    • 这似乎行得通,但既然我没有使用那个端,为什么有必要呢?
    • 这是必要的,因为 grep 在读取管道时阻塞,等待写入端的所有副本关闭。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-19
    • 1970-01-01
    • 2016-02-26
    相关资源
    最近更新 更多