使用fork()的C程序进程生成行为与运行结果确认咨询
代码运行行为验证与逻辑解析
你观察到的11个进程的运行结果完全符合代码逻辑,不存在异常。以下是详细执行流程拆解:
核心规则提前明确
- 子进程从fork处获得父进程地址空间的独立拷贝,所有变量值与父进程fork时完全一致,后续父子进程修改变量互不干扰。
- 只有初始主进程会完整执行外层
i循环的两次迭代:所有fork产生的子进程执行到if (pid != getpid()) break;时,都会因为自己的pid不等于之前存储的父进程pid,直接跳出外层循环,不会进入下一轮i迭代。 - 内层
j循环规则:只要fork返回值非0(当前为父进程分支),就会再执行一次fork,随后直接break跳出内层循环;只有fork返回值为0的子进程会继续执行下一轮j迭代。
逐层执行流程拆解
我们将初始主进程(对应输出中的3749)记为P0,逐层分析:
第一轮外层循环:i=0
P0首先将自己的pid存入变量pid,此时内层j循环的上限为i+2=2,可执行j=0、j=1两次迭代:
- j=0:
P0执行第一次fork,生成子进程P1(对应3750)。P0分支:fork返回值为P1的pid(非0),进入if分支,再次fork生成子进程P2(对应3751),随后break跳出内层循环。P0判断自己的pid与存储的pid值相等,不触发外层break,等待进入下一轮i迭代。P2分支:作为P0第二次fork的子进程,直接从break后开始执行,判断自己的pid不等于存储的P0的pid,触发外层break,进入后续打印逻辑。P1分支:fork返回值为0,不进入if分支,j自增为1,继续内层循环。- j=1:
P1执行第一次fork,生成子进程P3(对应3753)。P1分支:fork返回值非0,进入if分支,再次fork生成子进程P4(对应3755),随后break跳出内层循环。判断自己的pid不等于存储的P0的pid,触发外层break,进入打印逻辑。P4分支:作为P1第二次fork的子进程,直接从break后执行,判断pid不等于P0的pid,触发外层break,进入打印逻辑。P3分支:fork返回值为0,不进入if分支,j自增为2,超出内层循环上限,内层循环结束。判断pid不等于P0的pid,触发外层break,进入打印逻辑。
- j=1:
i=0轮结束后,共生成P0、P1、P2、P3、P45个进程。
第二轮外层循环:i=1
只有P0会进入本轮循环,P0再次将自己的pid存入变量pid,此时内层j循环上限为i+2=3,可执行j=0、j=1、j=2三次迭代:
- j=0:
P0执行第一次fork,生成子进程P5(对应3752)。P0分支:fork返回值非0,进入if分支,再次fork生成子进程P6(对应3754),随后break跳出内层循环。i自增为2,不满足i<2的条件,外层循环结束,进入打印逻辑。P6分支:作为P0第二次fork的子进程,直接从break后执行,判断pid不等于P0的pid,触发外层break,进入打印逻辑。P5分支:fork返回值为0,不进入if分支,j自增为1,继续内层循环。- j=1:
P5执行第一次fork,生成子进程P7(对应3756)。P5分支:fork返回值非0,进入if分支,再次fork生成子进程P8(对应3757),随后break跳出内层循环。判断pid不等于P0的pid,触发外层break,进入打印逻辑。P8分支:作为P5第二次fork的子进程,直接从break后执行,判断pid不等于P0的pid,触发外层break,进入打印逻辑。P7分支:fork返回值为0,不进入if分支,j自增为2,继续内层循环。- j=2:
P7执行第一次fork,生成子进程P9(对应3758)。P7分支:fork返回值非0,进入if分支,再次fork生成子进程P10(对应3759),随后break跳出内层循环。判断pid不等于P0的pid,触发外层break,进入打印逻辑。P10分支:作为P7第二次fork的子进程,直接从break后执行,判断pid不等于P0的pid,触发外层break,进入打印逻辑。P9分支:fork返回值为0,不进入if分支,j自增为3,超出内层循环上限,内层循环结束。判断pid不等于P0的pid,触发外层break,进入打印逻辑。
- j=2:
- j=1:
i=1轮结束后,新增P5、P6、P7、P8、P9、P106个进程,累计共11个进程,和实际运行输出完全匹配。你疑惑的最末端3758、3759就是P7在j=2轮次fork生成的两个叶子进程。
内容的提问来源于stack exchange,提问作者The_Student
相关产品推荐
相关产品推荐

