You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

具体执行逻辑:

  1. fork前的printf("before the fork\n")自带换行,后续又主动调用fflush(stdout),fork时缓冲区为空,不会重复输出这段内容
  2. fork返回后父子进程各自执行printf("after the fork\n"),自带换行直接刷到终端,因此出现两次after the fork
  3. 子进程进入sleep(1),父进程调用wait()阻塞等待子进程退出
  4. 子进程休眠结束后执行printf("I'm child"),无换行内容留在缓冲区,子进程调用exit(0)时刷新缓冲区,输出I'm child无换行
  5. 父进程被唤醒,执行printf("I'm parent"),无换行内容留在缓冲区,父进程退出时刷新缓冲区,内容接在子进程输出之后

代码2输出说明

注释掉fork后的printf("after the fork\n")后,父子进程都不会输出这段内容:

  1. 父进程调用wait()阻塞,等待子进程执行完成
  2. 子进程休眠结束后输出I'm child无换行,退出时刷新缓冲区
  3. 父进程被唤醒后输出I'm parent无换行,退出时刷新缓冲区,两段内容直接拼接,就是你看到的I'm childI'm parent

代码3输出说明

注释掉父进程的wait()后,父子进程的执行顺序完全由内核调度决定,你看到的输出对应调度顺序为:

  1. fork返回后父进程先被调度,先执行printf("after the fork\n"),自带换行直接输出
  2. 父进程无wait(),直接执行printf("I'm parent"),无换行内容留在缓冲区,父进程退出时刷新缓冲区输出I'm parent无换行
  3. 子进程此时被调度,执行自己的printf("after the fork\n"),内容直接接在父进程未换行的输出之后,形成I'm parentafter the fork
  4. 子进程休眠结束后输出I'm child,退出时刷新缓冲区得到最终结果

内容的提问来源于stack exchange,提问作者unixwait

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 23:27:02