为了缩小CPU和RAM之间的速度不匹配,引入了硬件高速缓存内存(hardware cache memory)。硬件高速缓存基于著名的局部性原理(locality priciple),该原理既适用于程序结构也适用于数据结构。
80x86体系结构引入了一个叫行(line)的新单位。行由十几个连续的字节组成,它们以脉冲突发模式(burst mode)在慢速DRAM和快速的用来实现高速缓存的片上静态RAM(SRAM)之间传送,用来实现高速缓存。
高速缓存再被细分为行的子集。在一种极端的情况下,高速缓存可以是直接映射的(direct mapped),这是主存个中的一个行总是存放在高速缓存中完全相同的位置。在另一种极端情况下,高速缓存是充分关联的(fully associative),这意味着主存中的任意一个行可以存放在高速缓存中的任意位置。但是大多数高速缓存在某种程度上是N-路组关联的(N-way set associative),意味着主存中的任意一个行可以存放在高速缓存N行中的任意一行中。
高速缓存单元插在分页单元和主内存之间。它包含一个硬件高速缓存内存(hardware cache memory)和一个高速缓存控制器(cache controller)。高速缓存内存存放内存中真正的行。高速缓存控制器存放一个表项数组,每个表项对应高速缓存内存中的一个行。每个表项有一个标签(tag)和表示高速缓存行状态的几个表示(flag)。这个标签由一些位组成,这些位让高速缓存控制器能够辨别由这个行当前所映射的内存单元。这种内存物理地址通常分为3组:最高几位对应标签,中间几位对应高速缓存控制器的子集索引,最低几位对应行内的偏移量。
当访问一个RAM存储单元是,CPU从物理地址中提取出子集的索引号并把子集中所有行的标签与物理地址的高几位相比较。如果发现某一个行的标签与这个物理地址的高位相同,则CPU命中一个高速缓存(cache hit);否则,高速缓存没有命中(cache miss)。
当命中一个高速缓存时,高速缓存控制器进行不同的操作,具体取决于存取类型。对于读操作,控制器从高速缓存行中选择数据并送到CPU寄存器;不需要访问RAM因而节约了CPU时间。因此,高速缓存起到了应有的作用。对于写操作,控制器可能采用以下两种基本策略之一,分别称之为通写(write-through)和写回(write-back)。在通写中,控制器总是既写RAM也写高速缓存行,为了提高写操作的效率而关闭高速缓存。回写方式只更新高速缓存行,不改变RAM的内容,提供了更快的功效。当然,回写结束以后,RAM最终必须被更新。只有当CPU执行一条要求刷新高速缓存表项的指令时,或者当一个FLUSH硬件信号产生时(通常在高速缓存不命中之后),高速缓存控制器才把高速缓存行写回到RAM中。
当高速缓存没有命中,高速缓存行被写会到内存中,如果有必要的话,把正确的行从RAM中取出放到高速缓存的表项中。
多处理器系统的每一个处理器都有一个单独的硬件高速缓存,因此它们需要额外的硬件电路用于保持高速缓存内容的同步。更新变得更耗时:自己一个CPU修改了它的硬件高速缓存,就必须检查其他CPU中是否有同样的数据;如果是,那么它必须通知其他CPU用适当的值更新数据。这种活动叫做高速缓存侦听(cache snooping)。这些都在硬件级处理,内核无需关心。
多级缓存的一致性是由硬件实现的,Linux忽略这些硬件细节并假定只有一个单独的高速缓存。
处理器cr0寄存器的CD标志位用来启用或禁用高速缓存电路。这个寄存器中的NW标志位指明高速缓存是使用通写还是回写策略。
Pentium处理器高速缓存的另一个特点是,让OS把不同的高速缓存管理策略与每一个页框相关联。为此,每一个页目录项和每一个页表项都包含两个标志;PCD(Page Cache Disablt)标志指明当访问包含在这个页框中的数据时,高速缓存功能必须被启用还是禁用。PWT(page Write-Through)标志指明当把数据写到页框时,必须使用的策略是写回策略还是通写策略。Linux清楚了所有页目录项和页表项中的PCD和PWT标志;结果是:对于所有的页框都启用高速缓存,对写操作总是采用写会策略。