C语言fork()&&fork()||fork()代码输出次数不符的疑问求助
为什么这段fork代码会输出10次"Hello"而非16次?
你一开始算成16次是很自然的直觉——毕竟默认以为每个fork()都会让进程数翻倍,但这里的关键是逻辑运算符&&和||的短路求值特性,它们会根据前面的表达式结果,直接跳过后面的fork()调用,不是所有fork()都会被每个进程执行的!
我们一步步拆解代码的执行流程:
代码拆分
先把代码拆成两个关键部分:
int main(int c, char **v){ fork(); // 第1个fork fork() && fork() || fork(); // 第2、3、4个fork,带逻辑判断 printf("Hello\t"); }
先回忆fork()的返回值规则:
- 父进程会返回子进程的PID(非0值,在逻辑判断中视为
真) - 子进程会返回
0(在逻辑判断中视为假)
步骤1:第一个fork()
初始只有1个进程(记为P0),执行第一个fork()后:
- 产生1个子进程
P1 - 此时总进程数:2个(
P0和P1)
步骤2:分析fork() && fork() || fork()的执行
这部分是核心,我们先单独分析任意一个进程执行这段代码时的行为,再乘以步骤1的2个进程数。
对于任意进程X,执行这段代码的流程:
第一个逻辑前的fork(记为F1):
X作为父进程,得到F1的返回值为真(非0),继续执行&&右边的代码- 产生子进程
Xb,Xb得到F1的返回值为假(0),跳过&&右边的代码,直接进入||部分
处理
&&分支(父进程X的路径):- 执行
&&右边的fork(记为F2):X作为父进程,得到F2的返回值为真,此时F1 && F2结果为真,触发||的短路特性——直接跳过||右边的fork,这个分支最终保留1个进程- 产生子进程
Xa2,Xa2得到F2的返回值为假,此时F1 && F2结果为假,需要执行||右边的fork(记为F3),产生新的子进程,这个分支最终变成2个进程
- 执行
处理
||分支(子进程Xb的路径):- 因为F1返回
假,&&右边的F2直接跳过,执行||右边的F3:Xb作为父进程保留,产生子进程Xb1,这个分支最终变成2个进程
- 因为F1返回
单个进程执行这段代码后的总进程数
把上面的分支加起来:1(X的最终进程) + 2(Xa2分支) + 2(Xb分支) = 5个进程
总进程数计算
步骤1结束后有2个进程,每个执行完步骤2的逻辑后变成5个,所以总进程数是:2 × 5 = 10个。每个进程都会执行printf("Hello\t"),所以最终输出10次"Hello"。
为什么一开始算16是错的?
16是4个fork()每个都让进程数翻倍的结果(2^4=16),但实际上:
- 当
&&左边为假时,右边的fork()不会执行 - 当
||左边为真时,右边的fork()不会执行
这导致第3个和第4个fork()并不是所有进程都会执行,所以进程数不会每次都翻倍。
内容的提问来源于stack exchange,提问作者Ajay Kumar
相关产品推荐
相关产品推荐

