页高速缓存
页高速缓存是Linux kernel使用的主要的磁盘缓存技术。磁盘高速缓存是一种软件机制,它允许系统把存放在磁盘上的一些数据保留在内存中,以便对那些数据的再次访问不再需要访问磁盘。
Kernel在读取磁盘时,如果数据页不再高速缓存当中,就会将读出的磁盘数据填充到页高速缓存当中。通过将数据页在高速缓存当中驻留,从而使进程再使用该页时不再需要访问磁盘。
Kernel在把一页数据写到磁盘之前,首先检查页是否已经在高速缓存当中,如果不在,首先会将页数据填充到高速缓存当中。更新到磁盘I/O的动作不是立即进行的,而是会有一点延时,从而使进程有机会对写入的数据进一步修改,这就是内核的延迟写操作。
脏数据的同步
进程对页高速缓冲区中的数据修改之后,数据页被标记为”脏数据”,即把PG_Dirty标志置位。Linux系统允许对脏数据写入磁盘块设备的延迟操作,被认为是显著增加了系统I/O能力的一种机制。
在下列条件下,脏数据写入磁盘:
- 页高速缓存空间不足
- 变脏以来,太久没有过更新
- 进程通过系统调用(sync(),fsync(),fdataasync())来强行对将对快设备的更新同步到磁盘。Msync系统调用用来将内存映射状态下的脏数据刷新到磁盘。
Pdflush
Pdflush内核线程负责定期扫描缓存中的脏数据,并在合适的时候将其更新到磁盘。定时器一般是500分之一秒,可以通过/proc/sys/vm/dirty_writeback_centisecs文件调整这个值。 Pdflush线程的个数是根据情况动态调整的:
- 至少有2个,最多有8个pdflush线程。(通过/proc/sys/vm/nr_pdflush_threads参数)可以修改这些变量的值。
- 如果最近1s内,没有空闲的pdflush线程,就创建新的。
- 如果pdflush的空闲时间超过了1s,就删除一个pdflush。
Buffer/cache
Cache - 全称page cache。当进程发起对磁盘的读写操作时,主要用来在内存中缓存磁盘中的数据,与磁盘的同步由pdflush负责。
Buffer – 全称block buffer。Block buffer中存放的是bio结构体数据。BIO 结构体是VFS和 block layer之间的接口。通俗的理解,Block buffer是page cache和磁盘驱动器之间打交道的一层缓存。
系统页高速缓存的使用情况可以通过buffer/cache的监控数据来分析。
从文件读写角度来看,buffer多用于缓存文件的管理信息,如目录位置,inode信息等。Cache缓存的是文件内容。
由于CPU不能直接处理外设上的数据,buffer用来标记那些文件的位置等描述信息。Cache主要目的是增加传输性能,用于缓存文件内容。
Direct I/O
有一些更复杂的程序(通常称为自缓存应用程序),更愿意自己控制I/O的传输过程(),通过将O_DIRECT标志位置位,I/O数据的传送便绕过了页高速缓存。 出于以下原因,系统页高速缓存技术是有害的:
- 处理页高速缓存的多余指令,降低了read(),write()的效率
- Read(),write()系统调用不是在磁盘和用户空间直接传送,而是分成两步:在磁盘和内核空间,>在内核空间到用户空间。 与页高速缓存相关的系统参数
- /proc/sys/vm/dirty_background_ratio 表示系统可用内存中,最高可用于存储 dirty 数据的百分比。The maximum of percentage of((cache+free)-mapped)。缺省10%。
- /proc/sys/vm/dirty_ratio 表示进程产生的脏数据到达系统整体内存的百分比,此时触发pdflush进程把数据回写到磁盘。缺省设置40.
- /proc/sys/vm/dirty_expire_centisecs 表示脏数据在内存中驻留超过该值,pdflush会将该数据回写到磁盘。缺省是3000。
- /proc/sys/vm/dirty_writeback_centisecs 表示pdflush周期性间隔多久处理脏数据回写。