一道“fork + 短路求值”经典题:到底会创建多少个进程?
该代码通过多个fork()调用创建子进程。关键点在于理解fork() && fork() || fork()的短路求值逻辑:父进程返回真值,子进程返回假值,导致不同分支会跳过部分fork()。初始进程依次执行fork()(×2)、短路表达式(×5)和fork()(×2),最终共20个进程(包含main)。题目要求不算main进程,故创建19个子进程,正确答案为B。解题需注意&
·
问题描述
代码如下(不算 main 进程本身,问总共创建了多少个子进程):
int main(int argc, char* argv[])
{
fork();
fork() && fork() || fork();
fork();
}
选项:A.18 B.19 C.20 D.21
先把结论放前面
- 程序最终一共会有 20 个进程(包含最初的
main进程) - 因为题目要求“不算
main进程本身”,所以创建的子进程数为:20 - 1 = 19 - 正确选项:B.19
必备知识点:fork 返回值 + C 里的真假
1)fork() 做了什么?
fork() 会复制当前进程,产生一个子进程:
- 在父进程中,
fork()返回 子进程 pid(>0) - 在子进程中,
fork()返回 0 - 失败返回 -1(本题默认不考虑失败)
2)C 语言中真假如何判断?
0表示 假(false)非 0表示 真(true)
所以:
- 父进程里
fork()的返回值为真 - 子进程里
fork()的返回值为假
本题的灵魂:&& / || 的短路求值 + 优先级
1)优先级
在 C 语言里:&& 的优先级 高于 ||
因此这句:
fork() && fork() || fork();
等价于:
( fork() && fork() ) || fork();
2)短路规则(务必牢记)
A && B:如果A为假,则 不再计算 BA || B:如果A为真,则 不再计算 B- 运算从左到右求值
逐行计算:进程数怎么变
我们按“每一行执行后,进程数乘几”来算。
第 1 行:fork();
每个进程执行一次 fork(),都会一分为二:
- 1 个进程 → 2 个进程
- 也就是:×2
第 2 行:(fork() && fork()) || fork()
这一行最容易错。关键点:不同分支会不会继续执行后面的 fork(),取决于短路。
下面用“一个进程进入这一行”为例,算这一行最终会变成多少个进程。
可视化流程图(Mermaid)
用“分支计数法”数进程
设进入这一行前只有 1 个进程:
-
先执行第一个
fork()(记作 F1)- 变成 2 个进程
- 父进程:F1 返回真
- 子进程:F1 返回假
-
对父进程(F1 为真):
- 需要继续算
&&右侧,于是执行第二个fork()(F2) - F2 又把该父分支变成 2 个进程
- F2 父:
true && true为真 →||短路 → 不执行第三个 fork - F2 子:
true && false为假 → 进入||右侧 → 会执行第三个 fork(F3),再分裂一次
- F2 父:
- 需要继续算
-
对子进程(F1 为假):
&&短路:第二个fork()不执行- 直接进入
||右侧:会执行第三个fork()(F3),再分裂一次
把最终的进程数列一下(从 1 个进程进入该行开始):
- F1 父 + F2 父:1 个(不会执行 F3)
- F1 父 + F2 子:会执行 F3 → 2 个
- F1 子:会执行 F3 → 2 个
总计:1 + 2 + 2 = 5
所以这一行的效果是:
- ×5
经验化记忆:
(fork() && fork()) || fork()每个进入的进程最终会变成 5 个。
第 3 行:fork();
最后一行再次每个进程一分为二:
- ×2
汇总:最终进程数与创建进程数
设最开始只有 1 个 main 进程:
| 语句 | 乘法因子 | 执行后总进程数 | ||
|---|---|---|---|---|
| 初始 | - | 1 | ||
fork(); |
×2 | 2 | ||
| (fork() && fork()) | fork(); | ×5 | 10 | |
fork(); |
×2 | 20 |
- 最终总进程数(包含
main):20 - 创建的子进程数(不算
main):20 - 1 = 19
常见坑位总结
- 忘了
&&优先级高于||,没加括号就按错误方式理解表达式 - 忘了短路:以为每个分支都会把三个
fork()全执行 - 忘了题目“不算
main进程本身”:最终进程数要再减 1
小结
这类题的核心不是“fork 有多难”,而是:
fork()在父子进程中的返回值真假不同&& / ||的短路会让某些分支“跳过 fork”,从而改变进程增长倍率
更多推荐


所有评论(0)