Linux内核设计与实现 十六、页高速缓存和页回写

it2026-03-16  1

页高速缓存

概念  Linux内核实现磁盘缓存,将磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。可以减少对磁盘的I/O操作。

性能提升 ●访问磁盘的速度要远低于访问内存的速度。因此从内存访问数据比从磁盘访问更快。 ●数据一旦被访问,就很有可能在短期内再次被访问到。

16.1 缓存手段

 页高速缓存是由内存中的物理页面组成的,其内容对应磁盘上的物理课。

 当内核开始读操作,会首先检查需要的数据是否在页高速缓存中。

写缓存

进程写磁盘时,缓存使用方式: ●不缓存:  高速缓存不去缓存任何写操作。当对缓存中的数据片进行写时,将直接跳过缓存,写到磁盘,同时也使缓存中的数据失效。这种策略效率较低 ●写透缓存  写操作会更新缓存,同时更新磁盘文件。写操作会立刻穿透缓存到磁盘中。这种策略对保持缓存一致性很有好处。 ●回写(Linux采用)  程序直接写到缓存中,后端存储不会立刻直接更新,而是将页高速缓存中被写入的页面标记成“脏”,并加入脏页链表中。然后由一个回写进程周期将脏页链表中的页写回到磁盘,保持磁盘和内存数据一致,并清理“脏”页标志。

缓存回收

原因 缓存算法最后涉及的重要内容是缓存中的数据如何清除:如为更重要的缓存项腾出位置,或者是收缩缓存大小,腾出内存给其他地方使用。 做法  Linux缓存回收是通过选择干净页(不脏)进行简单替换,如果缓存中没有足够的干净页面,内核将强制地进行回写操作,回收脏页,以腾出更多的干净可用页。

回收策略 ●理想回收策略:回收以后最不可能使用的页面。但这种策略太理想,无法真正实现。 ●最近最少使用(LRU):  思想:LRU回收策略跟踪每个页面的访问踪迹,以便能回收最老时间戳的页面。  优点:该策略的良好效果源自于缓存的数据越久未被访问,则月不大可能近期再被访问,而最近访问的最有可能被再次访问。  缺点:许多文件被访问一次,再不被访问的情景下,LRU效果很差,将这些页面放在LRU链的顶端显然不是最优。

●双链策略(LRU/2)  Linux实现的是一个修改过的LRU,也称为双链策略。Linux维护的不再是一个LRU链表,而是维护两个链表:活跃联播和非活跃链表。活跃链表上的页面不会被换出,而非活跃链表上的页面则是可以被换出的。  两个链表需要保持平衡,如果活跃链表超过了非活跃链表,那么活跃链表的头页面将会重新移回到非活跃链表中,以便能再次回收,就可以解决传统LRU算法中仅访问一次的问题。

应用场景

 打开大量源文件时,文件存储在页高速缓存中,从一个文件跳到另一个文件将瞬间完成。  编辑文件时,存储文件也会瞬间完成,因为写操作只需要写到内存,而不是磁盘。  编译项目时,缓存的文件将使得编译过程更少访问磁盘,所以编译的速度就加快了。

16.2 Linux页高速缓存

 本节剖析具体的数据结构以及内核如何使用它们管理缓存。

address_space对象

Linux页高速缓存使用了一个新对象管理缓存项和页I/O操作。该结构体是虚拟地址vm_area_struct的物理地址对等体。

具体见书

16.3 缓冲区高速缓存

 对于linux来说,2.4之前的内核中有两种缓存,一种是vfs的页高速缓存,另外一种是缓冲区高速缓存,实际上缓冲区对应于磁盘块,就是磁盘块在内存中的表示罢了,其中的数据也还是文件中的数据,只不过页高速缓存是按照页面管理的,而缓冲区高速缓存是按照块来管理的,两个缓存在数据本身上有一定的重合,这就造成了冗余,在内核中是很不好的,比如123456是页高速缓存的数据,到了缓冲区高速缓存,其实还是123456,只不过不再这么排列了,而是分成了一块一块的,比如1,2,3,…如果能将这些1,2,3指向页高速缓存,那么就可以不再需要为缓冲区高速缓存分配大量的内存空间了。2.4往后的内核就是这么做的,到了2.6内核,有了bio,那么buffer_head再也不用作为IO容器了

16.4 flusher线程

由于页高速缓存的缓存作用,写操作实际上会被延迟。flusher线程在系统中的空闲内存低于一个特定的阈值时,将脏页刷新写回磁盘。

最新回复(0)