【问题标题】:If I fork() and then do an execv(), who owns the console?如果我 fork() 然后执行 execv(),谁拥有控制台?
【发布时间】:2014-02-24 22:44:40
【问题描述】:

我正在编写一个 Linux 应用程序。如果我调用fork() 然后运行一个接受控制台输入的应用程序会发生什么?考虑下面的代码:

int process_id = fork();

if (process_id != 0) {
    /* this is the parent process */
    error = execv("../my_other_app", "parameter1", NULL);
    if (error < 0) {
        printf("error!");
    }
} else {
    /* this is the child process. Wait for my_other_app to set up */
    sleep(3);
    /* now continue */
}

printf("########## press ENTER to stop ##########\n");
getchar();

exit(0);

问题是,my_other_app 也有一个 按 ENTER 停止消息。那么当我调用getchar() 时,哪个应用程序正在读取它?主应用还是我用execv启动的my_other_app

编辑:通过测试,my_other_app 似乎优先于控制台。每次都会出现这种情况吗?有没有办法确保控制台归主进程所有?

【问题讨论】:

    标签: c linux multithreading fork execv


    【解决方案1】:

    两个进程都将它们的stdin 连接到终端(或任何原始进程的stdin 连接到)。当您致电 execv 时,这不会改变。如果两个进程同时尝试从stdin 读取,则无法预测哪一个会获得输入。

    如果您想断开子进程与终端的连接,您应该在调用execv 之前调用setsid() 将其放入自己的会话并移除其控制终端。

    【讨论】:

    • 请注意,您所说的断开连接并不会阻止孩子从控制台阅读;您必须将标准输入重新连接到其他地方以防止这种情况发生。当控制进程退出时,它确实会阻止向子进程发送 SIGHUP。
    • 没这么简单。查找“作业控制”以了解详细信息。
    • 然后我是否使用我在执行fork() 时捕获的进程 ID 停止 my_other_app,并在我准备停止它时向它发送终止信号?
    • 是的,你可以这样做。
    • 子进程中的 setsid() 似乎不起作用。按ENTER 仍然退出my_other_app
    【解决方案2】:

    fork() 在每个文件描述符上调用 dup()。实际上,您获得了孩子中所有文件的副本。一些“进程”(通过钩子)可能会检测到fork() 并关闭一些文件描述符,但这不太可能。某些文件可能会以特定标志打开,表明它应该在execv() 上关闭。 stdin 不是其中之一。

    你有两个解决办法,在子进程中关闭stdin,但是那样会导致问题,或者换成/dev/null

    freopen("/dev/null", "r", stdin);
    

    您可以对 stdoutstderr 执行相同的操作。


    在程序末尾添加“永远等待”(因为您不能再执行 getchar()):

    for(;;) sleep(0x7FFFFFFF); // for(;;) is probably superfluous
    

    这可能是最简单的方法,还有很多其他方法,例如在您知道永远不会更改的文件上使用 select()...

    【讨论】:

    • 在子进程上关闭标准输出会阻止它向控制台转储输出吗?那真是太棒了。
    • 为标准输出做一个freopen("/dev/null", "w", stdout)。然后不再倾倒。关闭的问题是,如果你有一个printf("something\n");,那么它不太可能崩溃,因为 FILE * 现在无效。
    • 看起来freopen("/dev/null", "r", stdin); 不太适合我,因为从/dev/null 读取时它会立即发出EOF 信号。我的程序有一个 getchar() 调用将终止它,并且似乎立即执行。如何让它忽略键盘输入并让我手动通过 PID 杀死它?
    • 我更新了我的答案。一个简单的 sleep() 数字如此之大,以至于您无论如何都必须重新启动计算机,否则它会在进程再次唤醒之前因老化而死。
    • 啊,真可惜。我无法修改该程序的行为。 getchar() 预计会在其他用途​​中终止它。
    【解决方案3】:

    我认为似乎my_other_app 具有优先权,因为另一个子进程具有sleep(3)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-26
      • 2013-12-15
      • 2012-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多