除非特别说明,否则本文提到的写操作都是 buffer write/write back。
前几天讨论到一个问题:Linux 下文件 close成功,会不会触发 “刷盘”?
其实这个问题根本不用讨论,查一下就知道。
man 2 close
的 NOTES
一节里有这么一段话:
A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a filesystem to flush the buffers when the stream is closed. If you need to be sure that the data is physically stored use fsync(2). (It will depend on the disk hardware at this point.)
所以,一个文件的描述符被 close 成功,并不会触发操作系统刷盘。
那么,问题来了,除了主动调用fsync
(或相关函数)之外,Linux 什么时候会“刷盘”呢?
一次写数据的典型流程(不考虑异常和其它特殊情况):
1、数据在用户态的 buffer 中,调用 write 将数据传给内核;
2、数据在 Page Cache 中,返回写入的字节数(成功返回);
3、内核将数据刷新到磁盘。
第二步如果返回成功,说明数据已经到达操作系统的Page Cache,可以保证的是如果进程挂了,但是操作系统没挂,数据不会丢失。
如果调用 fsync
将数据刷新到磁盘上,返回成功,说明数据已经刷新到硬件上了——我们一般认为如果 fsync
返回成功,则表示数据持久化成功。
那么,如果不调用fsync或其它类似功能的接口,Page Cache 是什么时候刷回磁盘的呢?
简单总结一下,有两种情况:
1、脏页太多。
2、脏页太久。
这些都由 Linux 内核的后台线程执行。相关的控制参数有:
说明: centy 中文意思是“百分之十”。
$ sysctl -a | grep dirty
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 5
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 10
vm.dirty_writeback_centisecs = 500
触发刷新脏页的条件:
1、调用fsync等。
2、脏页太多(相关参数:dirty_background_ratio与dirty_ratio)。
3、脏页太久(相关参数:dirty_expire_centisecs)。