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

Fork系统调用中文件描述符与I/O缓冲区的处理问题

关于fork复制文件描述符与I/O缓冲区的问题解答

核心原因在于C标准库的缓冲策略差异,fork本身不会主动刷新任何缓冲区,两个案例的区别完全由输出目标的缓冲模式决定:

案例1:输出到stdout(终端)时的情况

当stdout指向终端设备时,默认采用行缓冲模式。你代码中的printf("start")即便没有换行符,实际运行时也可能因终端交互特性、后续进程退出时的自动刷新,导致缓冲区内容被一次性输出;fork时子进程复制的是空缓冲区,因此"start"只打印一次。

你之前认为“fork在复制缓冲区前刷新了I/O缓冲区”是误解——fork本身不会执行刷新操作,问题根源是终端输出的行缓冲特性。

案例2:输出到文件时的情况

当输出目标是普通文件时,C标准库默认采用全缓冲模式。fprintf(fd, "Started\n")执行后,数据只会留在用户空间的缓冲区中,不会立即写入磁盘。此时调用fork,子进程会完整复制父进程的整个地址空间,包括这个未刷新的缓冲区。后续:

  • 子进程调用fclose(fd)时,会自动刷新缓冲区,将"Started\n"写入文件
  • 父进程在wait后调用fclose(fd),同样会刷新自己的缓冲区,再次写入"Started\n"

最终文件中就会出现两次"Started\n"。

针对测试代码的解决方案

要避免重复写入,只需在fork前主动刷新缓冲区即可:

fprintf(fd, "Started\n");
fflush(fd); // 主动刷新缓冲区,将数据写入磁盘
pid = fork();

这样fork时缓冲区已经是空的,父子进程后续的写入就不会重复输出"Started\n"。

另外,也可以在fork后只让一个进程负责关闭文件并刷新缓冲区,或者打开文件时指定无缓冲模式(fopen("filename.txt", "wb", _IONBF)),不过主动刷新是最直观的解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 01:50:55