页高速缓存和页回写
页高速缓存是linux内核实现磁盘缓存。它主要用来减少对磁盘的I/O操作。具体地讲,是通过把磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。
磁盘高速缓存之所以在任何现代操作系统中尤为重要源自两个因素:第一,访问磁盘的速度要远远低于访问内存的速度,因此,从内存访问数据比从磁盘访问速度要快,若从处理器L1和L2高速缓存访问则更快。第二,数据一旦被访问,就很有可能在短期内再次被访问到。这种在短期内集中访问同一片数据的原理称为临时局部原理。临时局部原理能保证:如果在第一次访问数据时缓存它,那就极有可能在短期内再次被高速缓存命中(访问到高速缓存中的数据)。正是由于内存访问要比磁盘访问快得多,再加上数据一次被访问后更可能再次被访问的特点,所以磁盘的内存缓存将给系统存储性能带来质的飞跃。
页高速缓存是由内存中的物理页面组成的,其内容对应磁盘上的物理块。页高速缓存大小能动态调整--它可以通过占用内存以扩张大小,也可以自我收缩以缓解内存使用压力。我们称正被缓存的存储设备为后备存储,因为缓存背后的磁盘无疑才是所有缓存数据的归属。当内核开始一个读操作(比如进程发送一个read()系统调用),它首先会检查需要的数据是否在页高速缓存中。如果在,则放弃访问磁盘,而直接从内存中读取。这个行为称作缓存命中。如果数据没有在缓存中,称为缓存为命中,那么内核必须调用块I/O操作从磁盘去读取数据。然后内核将读来的数据放入也缓存中,于是任何后续相同的数据读取都可命中缓存了。
在把一页数据写到块设备之前,内核首先检查对应的页是否已经在高速缓存中,如果不在,就要先在其中增加一个新项,并用要写到磁盘中的数据填充该项。I/O数据的传送并不是马上开始,而是要延迟几秒之后才对磁盘进行更新,从而使进程有机会对要写入的磁盘的数据做进一步的修改(就是内核执行延迟的写操作)。
内核的代码和内核数据结构不必行磁盘读,也不必写入磁盘,因此,页高速缓存中的页可能是下面的类型:
页高速缓存中的每个页所包含的数据肯定属于某个文件。这个文件(或者更准备地说是文件的索引节点)就称为页的所有者。几乎所有的文件读和写操作都依赖于页高速缓存。
内核设计者实现页高速缓存主要为了满足下面两张需要:
快速定位含有给定所有者相关数据的特定页。为了尽可能充分发挥页高速缓存的优势,对它应该采用高速的搜索操作。记录在读或写页中的数据是应当如何处理高速缓存中的每个页。例如,从普通文件、块设备文件或交换区读一个数据页必须用不同的实现方式,因此内核必须根据页的所有者选择适当的操作。页高速缓存中的信息单位显然是一个完整的数据页。一个页中包含的次盘口在物理上不一定是相邻的,所以不能用设备号和块号来识别它,取而代之的是,通过页的所有者和所有者数据中的索引来识别也高速缓存中的页。
address_space对象:页高速缓存的核心数据结构式address_space对象,它是一个嵌入在页所有者的索引节点对象中的数据结构。高速缓存中的许多也可能属于同一个所有者,从而可能被连接到同一个address_space对象。该对象还在所有者的页和对这些页的操作之间建立起链接关系。
每个页描述符都包括页链接到页高速缓存的两个字段mapping和index。mapping字段指向拥有页的索引节点的address_space对象,index字段表示在所有者的地址空间中页大小为单位的偏移量。也就是在所有者的磁盘映像中页的数据的位置。在页高速缓存中查找页时使用这两个字段。