【问题标题】:fork/pipe/dup2 issue: child process never exitsfork/pipe/dup2 问题:子进程永远不会退出
【发布时间】:2014-01-21 02:28:39
【问题描述】:

我想编写一个小程序,打印出一个长列表,可以通过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-- 剪裁,因此我知道基本管道设置正在运行。
  • 如果我在整个列表完成打印(退出 more 进程)之前按 [q],则程序(父/子)按预期退出

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

父进程卡在waitmore 进程没有退出,即使我已经关闭了父级中的两个管道

【问题讨论】:

    标签: c linux fork pipe dup2


    【解决方案1】:

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

    close(1);
    

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

    【讨论】:

    • 不幸的是,这不起作用。杀死寻呼机会导致父进程几乎立即退出,因为没有什么可以等待的。此更改根本不会打印任何输出。
    • 您尝试过使用 SIGTERM 吗?
    • 是的,我刚刚复制了它。
    • 我更新了我的答案,因为我发现了问题。现在为我工作。
    • 感谢您的建议。请注意,我正在关闭父级中的 pipe[1] 和 pipe[0]。为了实现正确的行为,关闭管道[1] 和 fd(1) 是必要的。仅关闭 fd(1) 或仅关闭 pipe[1] 存在原始问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多