C语言多次调用fork()后进程输出错误且无法终止问题
问题原因分析
1. 进程创建逻辑导致进程数远超预期
你这段代码总共会产生10个独立进程,计算逻辑如下:
- 初始进程执行
int n1 = fork()后生成2个进程:- 父进程(n1>0):后续执行
int n5 = fork(),再新增1个子进程,该分支总共2个进程 - 第一个子进程(n1==0):连续执行3次fork,每次fork都会让当前进程数翻倍,最终产生2^3=8个进程
所有10个进程都会执行最后的printf语句。
- 父进程(n1>0):后续执行
2. 打印顺序混乱、输出不连续的原因
- 系统调度器对进程的执行顺序是随机的,父子进程没有固定的先后执行顺序,不会按照代码编写顺序依次打印
- 如果父进程先于子进程执行完毕退出,当前shell会立刻弹出提示符,后续还没执行的子进程再打印内容时,就会出现在提示符之后,看起来像是程序重新运行才输出的内容。
3. 父进程PID错误的原因
当父进程先退出后,还没运行完的子进程会变成孤儿进程,被系统的init进程(PID通常为1,部分系统为systemd等管理进程)收养,所以此时调用getppid()返回的是收养进程的PID,而不是原来的父进程PID,这就是你看到的"PID错误"现象。
4. 程序无法正常终止的原因
你在父进程中没有调用wait()/waitpid()等待子进程执行完毕,父进程跑完自己的逻辑就直接退出了,shell感知到主进程退出就会认为程序执行完成,但后台还有孤儿进程在运行,给你一种程序没终止的错觉。如果有子进程进入异常阻塞状态,还会一直残留在后台占用资源。
修复方案
如果要实现所有进程按预期打印、父进程等所有子进程退出后再结束,可以参考修改后的代码:
#include <stdio.h> #include <unistd.h> #include <sys/wait.h> #include <stdlib.h> int main(int argc, char** argv) { int n1 = fork(); if (n1 == 0) { int n2 = fork(); int n3 = fork(); int n4 = fork(); printf("%d with parent %d\n", getpid(), getppid()); fflush(stdout); exit(0); } else if (n1 > 0) { int n5 = fork(); if (n5 == 0) { printf("%d with parent %d\n", getpid(), getppid()); fflush(stdout); exit(0); } } while (wait(NULL) > 0); printf("%d with parent %d\n", getpid(), getppid()); return 0; }
内容的提问来源于stack exchange,提问作者koala90
相关产品推荐
相关产品推荐

