FYI
广义上Cache的同步方式有两种,即Write Through(写穿)和Write back(写回). 从名字上就能看出这两种方式都是从写操作的不同处理方式引出的概念(纯读的话就不存在Cache一致性了,不是么)。对应到Linux的Page Cache上所谓Write Through就是指write()操作将数据拷贝到Page Cache后立即和下层进行同步的写操作,完成下层的更新后才返回。而Write back正好相反,指的是写完Page Cache就可以返回了。Page Cache到下层的更新操作是异步进行的。
Linux下Buffered IO默认使用的是Write back机制,即文件操作的写只写到Page Cache就返回,之后Page Cache到磁盘的更新操作是异步进行的。Page Cache中被修改的内存页称之为脏页(Dirty Page),脏页在特定的时候被一个叫做pdflush(Page Dirty Flush)的内核线程写入磁盘,写入的时机和条件如下:
当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。
当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘。
用户进程调用sync(2)、fsync(2)、fdatasync(2)系统调用时,内核会执行相应的写回操作。
Flush策略由以下几个参数决定(数值单位均为1/100秒):
# flush每隔5秒执行一次
root@082caa3dfb1d / $ sysctl vm.dirty_writeback_centisecs
vm.dirty_writeback_centisecs = 500
# 内存中驻留30秒以上的脏数据将由flush在下一次执行时写入磁盘
root@082caa3dfb1d / $ sysctl vm.dirty_expire_centisecs
vm.dirty_expire_centisecs = 3000
# 若脏页占总物理内存10%以上,则触发flush把脏数据写回磁盘
root@082caa3dfb1d / $ sysctl vm.dirty_background_ratio
vm.dirty_background_ratio = 10
默认是写回方式,如果想指定某个文件是写穿方式呢?即写操作的可靠性压倒效率的时候,能否做到呢?当然能,除了之前提到的fsync()之类的系统调用外,在open()打开文件时,传入O_SYNC这个flag即可实现。
文件读写遭遇断电时,数据还安全吗?相信你有自己的答案了。使用O_SYNC或者fsync()刷新文件就能保证安全吗?现代磁盘一般都内置了缓存,代码层面上也只能讲数据刷新到磁盘的缓存了。当数据已经进入到磁盘的高速缓存时断电了会怎么样?这个恐怕不能一概而论了。不过可以使用hdparm -W0命令关掉这个缓存,相应的,磁盘性能必然会降低。