fork()后调用printf()且父进程执行wait()时的异常输出问题
造成输出差异的核心原因
所有差异都来自三个Linux系统和C标准库的基础机制叠加:
fork()调用会完整复制父进程的用户态地址空间,包括标准IO缓冲区内容、文件描述符状态等,父子进程后续执行完全独立,调度顺序由内核决定- 终端交互模式下
stdout默认是行缓冲:只有遇到换行符\n、主动调用fflush()、进程退出时,才会把缓冲区里的内容刷到终端实际输出 wait()的作用是让父进程阻塞挂起,直到子进程退出后才会继续执行后续代码
代码1输出说明
你贴出的输出1实际遗漏了末尾父进程的I'm parent内容,完整输出应该是:
before the fork after the fork after the fork I'm childI'm parent
具体执行逻辑:
- fork前的
printf("before the fork\n")自带换行,后续又主动调用fflush(stdout),fork时缓冲区为空,不会重复输出这段内容 - fork返回后父子进程各自执行
printf("after the fork\n"),自带换行直接刷到终端,因此出现两次after the fork - 子进程进入
sleep(1),父进程调用wait()阻塞等待子进程退出 - 子进程休眠结束后执行
printf("I'm child"),无换行内容留在缓冲区,子进程调用exit(0)时刷新缓冲区,输出I'm child无换行 - 父进程被唤醒,执行
printf("I'm parent"),无换行内容留在缓冲区,父进程退出时刷新缓冲区,内容接在子进程输出之后
代码2输出说明
注释掉fork后的printf("after the fork\n")后,父子进程都不会输出这段内容:
- 父进程调用
wait()阻塞,等待子进程执行完成 - 子进程休眠结束后输出
I'm child无换行,退出时刷新缓冲区 - 父进程被唤醒后输出
I'm parent无换行,退出时刷新缓冲区,两段内容直接拼接,就是你看到的I'm childI'm parent
代码3输出说明
注释掉父进程的wait()后,父子进程的执行顺序完全由内核调度决定,你看到的输出对应调度顺序为:
- fork返回后父进程先被调度,先执行
printf("after the fork\n"),自带换行直接输出 - 父进程无
wait(),直接执行printf("I'm parent"),无换行内容留在缓冲区,父进程退出时刷新缓冲区输出I'm parent无换行 - 子进程此时被调度,执行自己的
printf("after the fork\n"),内容直接接在父进程未换行的输出之后,形成I'm parentafter the fork - 子进程休眠结束后输出
I'm child,退出时刷新缓冲区得到最终结果
内容的提问来源于stack exchange,提问作者unixwait
相关产品推荐
相关产品推荐

