博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
perl I/O和缓存的关系
阅读量:6434 次
发布时间:2019-06-23

本文共 1146 字,大约阅读时间需要 3 分钟。

最近在查看日志时,突然发现信息没有及时写入日志,研究了很久,突然醒悟:原来是print的缓存原因。

顺着这个详细了解了下perl里的IO缓存机制:

1.正常情况下,操作系统的读写都有缓存(buffer/cache),不同操作系统缓存大小不同,大约8K字节,目的是提高处理效率。因为读写磁盘是一个很低效的操作(相对于内存),累积起来一次读写大量数据会比每次读写少量数据快很多。

2.如果文件句柄是链接到终端的,比如STDOUT(也可以是其他句柄)输出到终端,那么perl标准IO库会默认设置为行缓冲模式,它有两个性质:a)遇到换行符会输出缓存内容;b)遇到从终端读(STDIN)则输出缓存。所以在终端上运行程序一般都会立刻输出内容,除非没有加换行符。

3.如果文件句柄是链接到文件的,如:

STDOUT被重定向到文件% ./favorite > OUTPUT

那么它就不是行缓冲模式,而是会等到缓冲区满或者程序结束再输出。

这种情况下有时候就会出现文件内容一直为空,或者交互的时候一直在等待的问题。

4.有一个例外是STDERR,始终都默认为行缓冲模式。

5.如果想要取消缓冲模式,可以使用

$| = 1;或者$fh->autoflush(1);

之后,perl会立刻输出缓冲区内容。

6.举例:

print "FILE LISTING OF DIRECTORY $dir:\n";print "---------------------------------\n";system("ls -l $dir");print "---------------------------------\n";

如果是输出到终端或者设置了缓冲区立刻输出,那么它的输出顺序是正确的。如果输出重定向到文件,那么头两行print内容会在缓冲区内,而system()的内容在子进程运行结束后先输出进文件中,然后缓存的print内容在整个进程结束后才会写入文件,顺序就变化了。

7.STDOUT和STDERR输出到一个地方,并且使用缓存机制,当程序发生错误时,由于STDERR是行缓存的,所以它会先于STDOUT输出出来。

8.如果程序自身结束了,或者自己调用了die/exit等函数退出,那么缓冲区内容会最后输出出来。但是如果进程是被kill掉的,它的缓冲区内容就来不及输出。所以如果程序没有及时清空缓存,那么被kill之后,在日志文件里会没有数据或者只有部分不完整的数据(上一次buffer满了之后的输出)。

解决办法:在脚本中加入autoflush,每次print都直接输出,不进入buffer。

 

参考

 

转载于:https://www.cnblogs.com/starRebel/p/8359455.html

你可能感兴趣的文章
安装Xcode在Mac OS X10.7.3上
查看>>
timeit统计运行时间
查看>>
提高调试.net cf程序效率一些技巧
查看>>
boost::regex
查看>>
Ogre 2011-11-30
查看>>
一起谈.NET技术,.NET异步编程:IO完成端口与BeginRead
查看>>
Python 3.2 beta 2 发布
查看>>
随机信号的傅里叶分析
查看>>
[转]ASP.NET Core 指定环境发布(hosting environment)
查看>>
WinForm读取指定的config文件的内容
查看>>
SqliteHelper整理(转载)
查看>>
Global.asax或IHttpModule实现屏蔽ip和图片防盗链
查看>>
SOCKET CLOSE_WAIT 搜集
查看>>
认识数据地图
查看>>
【Programming Clip】06、07年清华计算机考研上机试题解答(个别测试用例无法通过)...
查看>>
eval()用法
查看>>
尽力而为
查看>>
教你如何将UIImageView视图中的图片变成圆角
查看>>
pku 2635 The Embarrassed Cryptographer 数论——素数筛选法+模拟大数除法
查看>>
还有什么不能做?——细谈在C#中读写Excel系列文章之一
查看>>