TLB
Translation Lookaside Buffer (TLB) 是一种内存页面转换的缓存,它在许多具有内存分页功能的系统中使用。 当处理器需要将给定的虚拟地址转换为物理地址时,首先要查询TLB。 在x86系统上,TLB未命中会由硬件透明处理。 仅当页面目录(page directory)/表条目(table entry)不存在于核心中时,才会通过页面错误异常通知操作系统。
使用含义
像常规的CPU缓存一样,TLB “几乎是” 透明的。 操作系统必须注意两种情况。
修改分页结构
TLB没有透明地告知对分页结构所做的更改。 因此,一旦发生这种变化,就必须刷新TLB。 在x86系统上,这可以通过写入页面目录基寄存器 (CR3) 来完成:
movl %cr3,%eax
movl %eax,%cr3
注意: 在页面目录/表条目中设置全局 (G) 位,将会阻止该条目被刷新。 这对于将中断处理程序固定到位很有用。
一种更好的刷新TLB的替代方法是使用 invlpg
指令,在进行小的映射修改 (创建,删除,更改) 时,应使用该指令代替上述方法。) invlpg
主要用于页面取消映射和重新映射例程中,以使先前的缓存转换无效。 如果未使用 invlpg
或其他TLB 刷新方法,则映射将保持缓存状态,从而产生不确定的后果。
但是,请注意,invlpg
指令是在i486 ISA中引入的,并且不是i386 ISA的一部分,因此i386-compatible内核在编译时需要根据目标计算机正确使用相关条件包含代码。 示例过程声明和源代码如下:
void vm_page_inval(void *);
#include <kconfig.h>
.globl vm_page_inval
vm_page_inval:
#if TARGET_MACHINE >= TARGET_MACHINE_I486
movl 4(%esp),%eax
invlpg (%eax)
#else /* TARGET_MACHINE < TARGET_MACHINE_I486 */
movl %cr3,%eax
movl %eax,%cr3
#endif
ret
请注意,仅在进程地址空间之间切换时才需要更改或重新加载CR3。 在大多数情况下,使用它来完全刷新TLB确实是相当不必要的。
多处理器一致性
以上在多处理器的情况下更为复杂。 如果另一个处理器也可能受到页表写入的影响 (由于共享内存或来自同一进程的多个线程),则还必须刷新这些处理器上的TLB。 这将需要某种形式的处理器间通信。