在 parent 进程完成打印之前 child 是否有理由不打印?

Is there a reason for the child to not to print until the parent process finishes printing?

#include <stdio.h>
#include <unistd.h>

int do_fork(int depth)
{
    if (!depth) {
        return fork();
    }

    int val = do_fork(depth - 1);

    printf("%d\n", val);

    return val;
}

int main()
{
    int val;
    scanf("%d", &val);
    do_fork(val);
}

我多次尝试这段代码,在几台不同的机器上使用了几个不同的值。不管数字有多大,我总是看到 child 的 pid 一个接一个地打印出来,中间没有零。只有当 pids 都打印出来时,child 才开始打印零。

Here 是输入为 1000 的示例。

这种现象是有原因的还是随机的?

无法保证谁先跑。粒度确实很重要。尝试 5000,您将看到混合打印。这是我得到的结果:

Is there a reason for this phenomenon or is it just random?

C 和 POSIX 都没有任何规定来指导您观察到的特定输出,并且您可能会在某些机器上看到不同的结果。特别是,不同的操作系统和操作系统版本在 parent 或 child 是否先在 fork() 之后采用 CPU 可能会有所不同。 (即使在多核系统上,也只有其中一个可以立即占用执行 fork() 的核心。)

然而,fork do 产生的两个进程在内核中使用相同的打开文件描述进行打印,这意味着它们被主动阻止写入同时。这可能与您看到长时间运行相同输出的原因有关。一个进程获得一把锁,打印,释放锁,然后很快再次尝试获得锁。在这些情况下,同一个进程很可能在另一个进程获得锁之前重新获得锁。

此外,在 CPU 上实际安排新进程确实需要一些时间。这可能解释了 I 在您的程序中看到的输入超过大约 40 的行为,即大约 35 个非零输出,然后是零和非零之间相当严格的交替,然后是全零。

当然,以上所有内容都假设这两个进程是同时调度的。如果您只有一个核心同时为两者服务,那么很自然地每个核心都会在拥有核心的情况下产生自己的长期输出。这很容易表现为两个进程的输出根本没有混合。