linux的标准IO的buffer

今儿出了这么一事,由于做daemon进程时候stdin stout sterr没有重定向到/dev/null,当终端关闭后,句柄找不到对应的终端,导致程序崩溃了。
分析原因到原因后,用python测试了一下,发现如果用print每次输出的字符串小于1024,程序在标准IO无法正常得情况下不影响程序,但是一单超过1024或者一单有‘\n’ 就会触发 linux 的io error 5。
再次使用sys.stdout.write('xxx')函数进行测试,发现并不是每次输出小于1024就可以过,而是无论每次输出多少字符,累计一旦达到1024个字符 准确的说是最后一次write()的字符加上之前write综合大于1024就会触发io error 5。
根据以上的现象大胆猜测可能是存在一个默认1024的buff,查资料得知,IO有两种一种是unix io 就是咱们平时用的open write read close等方法,是unbuffer的IO,另外一种是与stream结合的标准IO也叫做buffer io,buffer分三种,分别是line buff、full buff、no buff , stderr默认是no buff,stdin跟stdout默认是line buff,这就解释了之前实验的现象 ,但是linux内核fd结构体里并没有buffer这么个属性,但是linux内核stream结构体标准IO的write,read等对stream的操作都是有buffer设定的,改变标准IO的buff size也可以通过linux内核自带的函数setvbuf()或者setbuf()来实现对stream结构体的buffer大小的改变。
回到python里 ,python打开标准IO用fdopen,以下是测试的python代码,用了这个代码,buffer从1024变成了512.
import Daemon
import time
import os
import sys
Daemon.Start() #变成守护进程
time.sleep(10)
fd=open("out.txt",'a')
fail=False
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 512) #设定为512B的buffer
for i in xrange(2048):
if not fail:
try:
sys.stdout.write('a'i)
out=str('a'
i)
except Exception,err:
out=str(err)
fail=True
fd.write(out)
else:
break

推荐阅读更多精彩内容