6.7.1 Linux使用的缓存

不管在硬件设计还是软件设计中,高速缓存是获得高性能的常用手段。Linux 使用了多种和内存管理相关的高速缓存。

1. 缓冲区高速缓存

缓冲区高速缓存中包含了由块设备使用的数据缓冲区。这些缓冲区中包含了从设备中读取的数据块或写入设备的数据块。缓冲区高速缓存由设备标识号和块标号索引,因此可以快速找出数据块。如果数据能够在缓冲区高速缓存中找到,则系统就没有必要在物理块设备上进行实际的读操作。

内核为每个缓冲区维护很多信息以有助于缓和写操作,这些信息包括一个“脏(dirty)”位,表示内存中的缓冲区已被修改,必须写到磁盘;还包括一个时间标志,表示缓冲区被刷新到磁盘之前已经在内存中停留了多长时间。因为缓冲区的有关信息被保存在缓冲区首部,所以,这些数据结构连同用户数据本身的缓冲区都需要维护。

缓冲区高速缓存的大小可以变化。当需要新缓冲区而现在又没有可用的缓冲区时,就按需分配页面。当空闲内存变得不足时,例如上一节看到的情况,就释放缓冲区并反复使用相应的页面。

2. 页面高速缓存

页面高速缓存是页面I/O操作访问数据所使用的磁盘高速缓存。我们在文件系统会看到,read( )write( )mmap( )系统调用对常规文件的访问都是通过页面高速缓存来完成的。因为页面I/O操作要传输整页数据,因此高速缓存中所保留的信息单元是一个整页面。一个页面包含的数据未必是物理上相邻的磁盘块,因此就不能使用设备号和块号来标识页面。相反,页面高速缓存中一个页面的标识是通过文件的索引节点和文件中的偏移量达到的。

与页面高速缓存有关的操作主要有三种:当访问的文件部分不在高速缓存中时增加页面,当高速缓存变得太大时删除页面,以及查找一个给定文件偏移量所在的页面。

 

3.交换高速缓存

只有修改后的(脏)页面才保存在交换文件中。修改后的页面写入交换文件后,如果该页面再次被交换但未被修改时,就没有必要写入交换文件,相反,只需丢弃该页面。交换高速缓存实际包含了一个页面表项链表,系统的每个物理页面对应一个页面表项。对交换出的页面,该页面表项包含保存该页面的交换文件信息,以及该页面在交换文件中的位置信息。如果某个交换页面表项非零,则表明保存在交换文件中的对应物理页面没有被修改。如果这一页面在后续的操作中被修改,则处于交换缓存中的页面表项被清零。 Linux 需要从物理内存中交换出某个页面时,它首先分析交换缓存中的信息,如果缓存中包含该物理页面的一个非零页面表项,则说明该页面交换出内存后还没有被修改过,这时,系统只需丢弃该页面。

这里给出有关交换缓存的部分函数及功能:位于/ linux/mm/swap_state.c 中。

 

初始化交换缓冲,设定大小,位置的函数:

extern unsigned long init_swap_cache(unsigned long, unsigned long);

 

显示交换缓冲信息的函数:

extern void show_swap_cache_info(void);

 

加入交换缓冲的函数:

int add_to_swap_cache(unsigned long index, unsigned long entry)

参数index是进入缓冲区的索引(index是索引表中的某一项),entry是‘页面表项’(即此页面在交换文件中的位置记录,这个记录类似页面表项,参见交换机制)

 

复制被换出的页面:

extern void swap_duplicate(unsigned long);

当使用copy_page_tables()调用,来实现子进程在fork()时继承被换出的页面,可参阅交换机制一节。

 

从缓冲区中移去某页面

delete_from_swap_cache(page_nr);

 

4       硬件高速缓存

常见的硬件缓存是对页面表项的缓存,这一工作实际由处理器完成,其操作和具体的处理器硬件有关(但管理要由软件完成),对这一缓存接下来要进一步描述。