fork / pipe / dup2问题:子进程永不退出

时间:2014-01-03 12:08:20

标签: c linux fork pipe dup2

我想编写一个小程序,通过more(或less)在终端中打印出一个可以分页的长列表,这样列表就可以了从头到脚检查......

该计划:

  • fork关闭执行more程序的子进程
  • 在父进程中,列表打印
  • 父/子之间设置pipe,以便父母打印到stdout的列表会发送到more程序的stdin

代码:

int main(int argc, char *argv[])
{
    int pager, status;
    int pipes[2];

    pipe(pipes);

    pager = fork();

    if (pager == 0) { // child

        dup2(pipes[0], 0);
        close(pipes[1]);
        char *args[] = {"more", NULL}; 
        execvp(args[0], args);

    } else { // parent

        dup2(pipes[1], 1);

        int x;
        for (x = 0; x < 500; x++) {
            printf("Hello World! %d\n", x);
        }  

        close(pipes[0]);
        close(pipes[1]);

        wait(&status);
    } 

    return 0;
}

我在大多数情况下都有这个工作:

  • “Hello World!...”消息的长列表打印在由--More--剪切的终端上,因此我知道基本的管道设置正在运行。
  • 如果我在整个列表完成打印之前按[q](退出more进程)程序(父/子)按预期退出

我遇到的唯一问题是,如果我一直按[space][return](这会推进more给出的输出)并到达我的列表末尾(第500个“) Hello World!...“消息”然后终端挂起。按[q]没有响应(我必须[ctrl+c]才能退出)。

父进程停留在wait上。 即使我已关闭父级中的两个管道,<{1}}进程也不会退出

1 个答案:

答案 0 :(得分:1)

在你的代码中,你正在关闭pipe[0],这不是你写给孩子的描述符。你做了dup2(pipes[1], 1)所以为了告诉孩子管子已经结束你必须关闭你写的那个。

close(1);

当然,如果您打算使用stdout继续您的流程,则必须恢复原始输出,因为现在将关闭它。