问题描述
#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);
}
我尝试了几次此代码,在不同的计算机上使用了几个不同的值。不管数字有多大,我总是看到孩子的pid彼此相邻打印,中间没有零。仅当所有pid都已打印时,子代才开始打印零。
是这种现象的原因吗?还是只是随机的?
解决方法
不能保证谁先运行。粒度确实很重要。尝试5000,您将看到混合打印。这是我得到的结果:
,是这种现象的原因吗?还是只是随机的?
C和POSIX都没有任何规定可以指导您观察到的特定输出,并且可能会在某些机器上看到不同的结果。特别是,在父级或子级在fork()
之后首先获取CPU方面,不同的操作系统和操作系统版本可能有所不同。 (即使在多核系统上,也只有其中一个可以立即采用执行fork()
的内核。)
但是,派生 do 的两个进程在内核中使用相同的打开文件描述进行打印,这意味着将积极地阻止它们同时写入。这可能与为什么您看到相同输出的长期运行有关。一个过程将获得一个锁,进行打印,然后释放该锁,并在尝试再次获取该锁之后不久。在这种情况下,同一个进程很有可能在另一个进程获得另一个锁之前就重新获得了该锁。
此外,确实需要一些时间才能在CPU上实际调度新进程。这可能可以解释行为 I 对于输入超过40的程序,即大约35个非零输出,然后在零与非零之间进行相当严格的交替,然后是全零的行为。
当然,以上所有假设都完全同时调度了两个进程。如果您只有一个核心同时为这两个核心提供服务,那么很自然地会得出,每个核心在拥有核心的情况下都会产生自己的长期输出。这很容易表现为两个过程的输出根本没有交织在一起。