IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

fork 与 IO 流的缓冲模式

Chen3feng's space 2009-11-02 12:25:40 累计浏览 3,577 次
本机暂存

    刚才帮人解决了一个问题,记录一下。

    一个 CGI 程序,输出一些内容,然后就 fork 子进程做一些耗时的操作,父进程马上退出以便返回结果给浏览器。

    现象是 CGI 的内容在浏览器上看到的是两次重复的,在程序的开头加日志记录运行次数,发现每次刷新浏览器,进程也只运行一次。如果不 fork,结果就是正确的。如果 fork,即使父子进程都马上返回,故障依然存在。但是在命令行调用这个程序,输出是正常的。

    猜测跟某些全局对象的析构有关,把 fork 后 return 0 改为 _Exit(0),浏览器就报错了,没收到完整的数据,其实是什么都没收到。

    恍然大悟,应该是 cout 的缓冲造成的,fork 前加了一句 cout.flush(),问题解决了。

    分析了一下原因:

    stdio流和C++ IO流都有三种工作模式:无缓冲,行缓冲,全缓冲。

    运行库会根据标准输出是否是终端而做出不同的优化:

    当程序在命令行前台启动时,设置为行缓冲模式,以便输出结果能尽快地被人看到。

    cgi 方式被调用时,运行库检测到标准输出被重定向,就开启全缓冲以提高性能,glibc 下缓冲区的大小是 4K,缓冲区不填满,就不会实际输出。这种情况下fork 的时候因为缓冲区还不满,实际并未输出,fork 后,父子进程分别结束,cout 析构的时候要输出所有的未输出的内容,因此现象上看起来就是输出了两次。

    把原来的程序输出重定性到文件即可复现这个 bug。

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. AWStats是一个基于Perl的WEB日志分析工具。 (累计阅读 7,176)
  2. github 上 Fork 别人的项目后的常用的操作指南 (累计阅读 4,776)
  3. 网关协议学习:CGI、FastCGI、WSGI (累计阅读 4,709)
  4. HTTP Server开发相关学习资料整理推介 (累计阅读 4,515)
  5. 在CGI中通过Etag和Cache-Control来控制流量,访问量及生效时间 (累计阅读 4,335)
  6. 一个小小的C 写的web server (累计阅读 3,760)
  7. Linux 系统文件描述符继承带来的危害 (累计阅读 3,710)
  8. python与c-跨语言级别的进程间通信 (累计阅读 3,430)
  9. 进程的一生 (累计阅读 3,286)
  10. 关于一个gzip压缩问题的定位解决 (累计阅读 3,034)