技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> Linux --> fork 与 IO 流的缓冲模式

fork 与 IO 流的缓冲模式

浏览:2627次  出处信息

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

    一个 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. PHP查询MySQL大量数据的内存占用分析    (阅读:3919)
  2. github 上 Fork 别人的项目后的常用的操作指南    (阅读:3846)
  3. 极不和谐的 fork 多线程程序    (阅读:2754)
  4. 多线程下的fork及写时复制导致的性能问题    (阅读:2700)
  5. PHP输出缓冲及其应用    (阅读:1700)
  6. 设置 linux 命令缓冲模式    (阅读:954)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1