2010年(30)
分类: LINUX
2010-06-25 17:27:56
实际工作中,有遇到一种情况,当TCP以优雅的方式关闭连接时,内核缓存的数据有时不能成功发送到对端,针对这种问题,一种解法是使用fsync或sync调用(该类函数作用下节详细说明),将内核缓冲的数据写到磁盘文件中,因此fflush只是将C库缓存数据flush到内核中,并不确保其可以写到磁盘文件。
以上是一种解法,这种解法并不是对所有情况都有效,实际还需做严格的测试,现在讲一下另一种可能的解决办法,即SO_LINGER选项.
我们知道TCP连接的关闭有两种方式,一种是正常的使用FIN包的关闭方式,称之为“优雅”的关闭,而另一种是直接发送RST强制关闭,默认情况下,系统采用优雅的方式关闭TCP连接,通过设置SO_LINGER可以达到强制关闭的目的。下面先来了解一下SO_LINGER的用法:
|
有以下三种情况:
从上可以看出,采用LINGER的方式,在socket关闭时等待一合适的时间也将获得一个比较好的响应。
<
传统的UNIX实现在内核中设有缓存区高速缓存或页面高速缓存,大多数磁盘I/O都通过缓冲进行。当将数据写入文件时,内核通常先将该数据复制到其中一个缓存区中,如果该缓冲区尚未写满,则并不将其排入输出队列,而是等待其写满或者当内核需要重用该缓存区以便存放其它磁盘块数据时,再将该缓冲排入输出队列,然后待其到达队首时,才进行实际的I/O操作。
这种输出方式称为延迟写。
延迟写减少了磁盘读写次数,但是却降低了文件内容的更新速度,使得欲写到文件中的数据在一段时间内并没有写到磁盘上。当系统发生故障时,这种延迟可能造成文件更新内容的丢失。
因此,为了保证磁盘上实际文件系统与缓冲区高速缓存中内容的致性,UNIX系统提供了sync、fsync和fdatasync三个函数。
3. fflush
|
通常在使用了fwrite后,为了让DATA尽快输出或写到磁盘文件,都会调用fflush,但根据fflush的MANpage,fflush只是强制将用户空间缓存的数据写到特定输出.因此,为了保证数据真正写到物理磁盘,还需要flush内核缓存.
NOTES:
Note that fflush() only flushes the user space buffers provided by the C library. To ensure that the data is physically stored on disk the kernel buffers must be flushed too, e.g. with sync(2) or fsync(2).
4.同步写(O_SYNC)
上面讲了,系统缺省情况下是采用延迟写的,经过设置后(设置O_SYNC)它也支持同步写,但与加了fsync或fdatasync的延迟写相比,O_SYNC在每次写文件时都要更新,这多用于数据库的操作,对其它操作来讲,fsync或fdatasync更具灵活性.