TLB

来自osdev
跳到导航 跳到搜索

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。 这将需要某种形式的处理器间通信。

另见

外部链接