【问题标题】:Child process executing parent code (lines before the fork) [duplicate]执行父代码的子进程(分叉前的行)[重复]
【发布时间】:2021-05-30 12:28:20
【问题描述】:

我很难理解fork() 的行为。我认为子进程将在fork()“之后”执行行。所以我希望只看到一个“Hello world!”,但是这段代码:

printf("Hello World!\n");
fork();
return 0;

输出两个“Hello World”。这是为什么呢?

我还从使用pipe() 的在线示例中注意到,管道是在分叉子节点之前创建的。父进程创建管道后,子进程怎么也有管道?

【问题讨论】:

  • 你能给我们最简单的完整代码来复制这个问题吗?这段代码是来自main 还是return 去某个地方?
  • 每个帖子问一个问题。关于输出出现两次的问题与关于为什么孩子和父母都有一个父母打开的管道的问题是分开的。
  • printf 函数被缓冲。它可以写入缓冲区,然后在您调用 fflush 或您的进程终止之前不刷新缓冲区。如果父母安排在正常终止时做一些您不希望孩子也做的事情,则不应允许两个分叉进程正常终止。

标签: c operating-system pipe fork unnamed-pipes


【解决方案1】:

第一个问题很可能与您程序的文件缓冲模式有关,它可能使用完全缓冲设置,这意味着只有在缓冲区 (stdout) 已满时才写入流,这会延迟输出,并且子进程也会输出,因为它有相同的stdout

如果您在 printf 之后使用 fflush(stdout),或者如果您将缓冲模式 (setvbuf) 更改为行缓冲或根本不缓冲,您将防止重复输出,因为它会在 @ 之前发生987654326@.

至于第二个问题,子进程在fork之后复制了父进程的代码,正如您正确提到的那样,但它也复制了文件表。通过在fork 之前创建未命名的管道,您将确保孩子具有相同的文件描述符。这通常用于设置子进程和父进程之间的管道通信。

您可以检查两个进程中的每一个的/proc/<process id>/fd 文件夹以确认这一点。

脚注

为了将来参考,这些是两个不同的主题,尽管是相切的,但它们属于不同的问题,您可以在这里看到其中一个问题,该问题与第一个问题相关的重复问题很接近,但不是第二个问题,尽管是偶然的它并没有没有得到答复,它仍然被埋在不同的问题中,并且几乎不会被其他用户发现。

【讨论】:

  • 如果子进程是父进程的副本,程序不应该因为 fork() 而创建无限数量的子进程吗?子进程是否跳过它被分叉()的行?
  • @9ganzi,代码只在fork后重复,我用程序行为的原因和解决方案更新了我的答案,
【解决方案2】:

当我们 fork 子进程时,会得到父进程地址空间的精确副本。所以应该预料到这种行为。管道系统调用返回一个文件描述符,父进程和子进程都有这个描述符。

【讨论】:

  • 这并没有回答为什么printf 的输出执行之前分叉出现两次的问题。
猜你喜欢
  • 1970-01-01
  • 2017-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 2018-05-11
相关资源
最近更新 更多