【问题标题】:What will happen if I fork and exec in parent and child?如果我在 parent 和 child 中 fork 和 exec 会发生什么?
【发布时间】:2017-04-12 22:10:46
【问题描述】:

这是我的名为 server.c 的示例代码(已删除包含以保持简单)。

int main()
{
    for(int i = 0; i < 10; i++) {
        fork();
        execl("./client", "./client", NULL);
    }
    if (wait(NULL) == -1)
        perror("error with wait");
    return 0;
}

这是从上述程序中执行的客户端代码。

int main()
{
    printf("This is the child with pid = %d from parent %d", getpid(), getppid());
    return 0;
}

现在让我解释一下我认为会发生什么以及我实际得到的输出。

在服务器中,我们进入 for 循环。在第一次迭代中,我们点击了 fork()。此时有两个进程,即父进程和第一个子进程。现在我们从这两个进程中执行一个名为“client”的程序。此客户端代码仅打印一些信息。所以当我运行这个服务器程序时,我应该得到两行,对吧?一条来自父母,另一条来自孩子?但是我只打印了一行,使用 strace 后我发现只有父母在打印东西,而不是孩子。那么这是为什么呢?

是不是因为孩子已经死了(这是正确的术语吗?),因为孩子已经被执行了?如果是这样,孩子会怎么样?变成丧尸了吧?它会被init收集吗?即便如此,为什么它不会在像僵尸一样结束之前打印出那一行?

【问题讨论】:

  • 当我尝试你的程序时,我收到了数百条 error with wait: No child processes 消息。
  • 没关系,我给客户端程序起了错误的名字。当我修复它时,它按预期工作,我得到了两行输出。
  • exec()之后,程序不存在。执行的exec在父子节点中执行。循环永远不会循环(如果 exec 成功)
  • @posixking。请不要接受我的回答。这不正确,我无法删除它..

标签: c linux fork exec execl


【解决方案1】:

如果标准输出连接到终端,它应该是行缓冲的,所以不需要刷新。并且所有流在关闭时都会自动刷新,这会在程序结束时发生。

也许你看到两个打印在同一行? 试试这个代码:

#include <stdio.h>
int main(int argc, char **argv) {
  printf("This is the child with pid = %d from parent %d\n", getpid(), getppid());
  return 0;
}

顺便说一句,您在printf 中缺少%d

【讨论】:

  • 如果标准输出连接到终端,它应该是行缓冲的,所以不需要刷新。所有流在关闭时都会自动刷新,这会在程序结束时发生。
  • 好点。我只是试图重新创建他的案例,但无法做到。你是对的。删除...
  • 谢谢,我的错,你是对的。我在stackoverflow中输入了换行符,但忘记在我的程序中输入它。换行符也会刷新流,所以它现在可以工作了。
  • @posixKing 没关系,因为返回会刷新。也许您只是没有看到这两条消息,因为它们在同一行上?
【解决方案2】:

你肯定会得到两条线。

如果不是,可能是由于您运行程序的方式。家长可能会打印并退出,如果您在此时停止查看或收听,您将丢失来自孩子的信息。

因此,请确保您直接从 shell 终端运行脚本,而不是脚本的一部分、IDE、编辑器或任何其他工具。

例如,这里是./server; echo "Done"的输出:

user ~ $ ./server; echo "Done."
This is the child with pid = 27904 from parent
Done.

这使它看起来只有一行输出。但是,在这之后的那一行,提示已经返回,并且子进程在其后面写了一些信息:

user ~ $ This is the child with pid = 27905 from parent

如果您以 shell 等待的方式运行脚本,例如添加 | cat,它将一直等到管道完全关闭,您可以更清楚地看到两者:

user ~ $ ./server | cat; echo "Done."
This is the child with pid = 27953 from parent
This is the child with pid = 27955 from parent
Done.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-24
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 2011-11-19
    • 2015-12-01
    • 1970-01-01
    相关资源
    最近更新 更多