1.1. 缓冲区高速缓存
缓冲区高速缓存中包含了由块设备使用的数据缓冲区。这些缓冲区中包含了从设备中读取的数据块或写入设备的数据块。缓冲区高速缓存由设备标识号和块标号索引,能快速找出数据。如果数据能够在缓冲区高速缓存中找到就不必在物理块设备上进行实际的读操作。
描述缓冲区的数据结构是buffer_head,缓冲区的大小一般比页小,所以一页中可以包含几个缓冲区,同一页中的缓冲区用链表连接。
由于Linux采用了这种缓存机制,所以当把一个数据写入文件时,内枋将会把该数据写入内存缓冲区,而不是直接写入磁盘。这样就很可能导致写磁盘的命令已经返回,而实际的写入磁盘的操作还未执行。为此用户应使用正确的关机命令关机,而不是直接关掉计算机的电源。用户也可以使用sync命令刷新缓冲区高速缓存,从而把缓冲区中的数据强制写到磁盘上。
1.2. 页高速缓存
页高速缓存用来加速对磁盘上的映像和数据的访问。页高速缓存用来缓存某个文件的逻辑内容,并通过文件的VFS索引节点和偏移量访问。页从磁盘上读到物理内存时就缓存在页高速缓存中。下面一段源代码就是把读入的页存于缓存中:
void add_to_page_cache_locked(struct page * page, struct address_space * mapping, unsigned long index)
{
spinlock_t * pg_lock;
if(!PageLocked(page))
BUG();
page_cache_get(page);
pg_lock=__PAGECACHE_LOCK(mapping, index);
spin_lock(pg_lock);
page->index=index;
add_page_to_inode_queue(mapping, page);
add_page_to_hash_queue(page, page_hash(mapping, index));
lru_cache_add(page);
spin_unlock(pg_lock);
}
1.3. 交换高速缓存
当将页交换到交换文件中时,Linux总是避免写页。页已经被交换出内存后若有进程再次访问时又要将它重新调入内存。只要页在内存中没有被写过,交换文件中的拷贝就是有效的。
Linux使用交换缓存来跟踪这些页。这个交换缓存是一个页表入口链表,每一个对应于系统中的物理页。交换缓存对应于交换出页的页表入口,并且描述页放置在哪个交换文件中以及在交换文件中的位置。如果交换缓存入口为非0值表示在交换文件中的这一页没有被修改。如果此页被修改(或者写入),则其入口将从交换缓存中删除。
当Linux需要将一个物理页交换到交换文件时,它将检查交换缓存。如果对应此页存在有效入口,则不必将这个页写到交换文件中。这是因为内存中这一页在最近一次由交换文件中读出后还没被修改过。
交换缓存中的入口是已换出页的页表入口。它们虽被标记为无效,但为Linux提供了页在哪个交换文件中以及文件中的位置等信息。
1.4. 硬件高速缓存
常见的硬件缓存是对页表项的缓存,如TLB。它通常在MMU内部,条目的数量较少。每一个TLB寄存器的每一个条目包含一页的信息:有效位、虚页位、修改位、保护位和页所有的物理页号。当一个虚地址被送到MMU翻译时,硬件先将其与TLB中的所有条目进行比较。如果虚页号在TLB中,且访问没有违反保护位,其页帧会直接从TLB中取出而不访问页表。如果页号在TLB中,但当前指令试图写一个只读的页,这时将发生页故障,与直接访问页表时相同。如果MMU发现在TLB中没有该页,就进行常规的页表查找,然后从TLB中淘汰一个条目,并把它替换为刚找到的页表项。