第 19 章 分页:快速地址转换(TLB)

分页机制因需要访问内存中的页表而带来巨大的性能开销。TLB(Translation-Lookaside Buffer) 作为地址转换的硬件缓存,是解决这一问题的核心。

核心问题

如何利用 TLB 加速地址转换?在 TLB 未命中时,硬件与操作系统如何高效协作?

TLB 基本原理

TLB 是 MMU 的一部分,缓存了频繁使用的虚拟到物理地址的映射。

1. 算法流程

硬件首先在 TLB 中查找 VPN:

  • TLB 命中:直接获取 PFN,速度极快(接近 CPU 频率)。
  • TLB 未命中:访问内存页表,更新 TLB,并重试指令。
VPN = (VirtualAddress & VPN_MASK) >> SHIFT
(Success, TlbEntry) = TLB_Lookup(VPN)
 
if (Success == True) { // TLB Hit
    if (CanAccess(TlbEntry.ProtectBits) == True) {
        Offset = VirtualAddress & OFFSET_MASK
        PhysAddr = (TlbEntry.PFN << SHIFT) | Offset
        AccessMemory(PhysAddr)
    } else {
        RaiseException(PROTECTION_FAULT)
    }
} else { // TLB Miss
    PTEAddr = PTBR + (VPN * sizeof(PTE))
    PTE = AccessMemory(PTEAddr)
    if (PTE.Valid == False) {
        RaiseException(SEGMENTATION_FAULT)
    } else if (CanAccess(PTE.ProtectBits) == False) {
        RaiseException(PROTECTION_FAULT)
    } else {
        TLB_Insert(VPN, PTE.PFN, PTE.ProtectBits)
        RetryInstruction() // 重新尝试指令,此时 TLB 已命中
    }
}

2. 局部性与性能

TLB 的成功源于程序的局部性(Locality)

  • 空间局部性:访问数组元素时,后续访问多在同一页内(仅首个元素触发 Miss)。
  • 时间局部性:循环变量等数据会被反复访问。

TLB 管理细节

1. 谁来处理未命中?

  • 硬件管理 (CISC/x86):硬件自动遍历页表并更新 TLB。
  • 软件管理 (RISC/MIPS):硬件抛出异常,由操作系统的陷阱处理程序查找页表并更新 TLB。优势在于灵活性和硬件简单性。

2. 上下文切换

TLB 映射仅对当前进程有效。切换进程时需处理冲突:

  • 方案 A:清空 (Flush):切换时将所有有效位置 0,但会导致新进程初期大量未命中。
  • 方案 B:ASID (地址空间标识符):在 TLB 项中增加 ASID 字段区分进程,支持跨进程共享 TLB。
VPNPFN有效位ASID
1010011
1017012

3. 替换策略

当 TLB 满时,通常采用 LRU(最近最少使用)随机(Random) 策略来选择替换项。

实际系统示例:MIPS R4000

  • 项结构:包含 VPN、PFN、G(全局位)、ASID、C(一致性)、D(脏位)、V(有效位)。
  • 管理指令:提供 TLBPTLBWI 等特权指令供 OS 管理。

小结

  • 成就:TLB 使虚拟内存性能接近原生物理内存。
  • 挑战TLB 覆盖范围限制了大型程序的性能。
  • 对策:采用大页(Huge Pages)虚拟索引缓存进一步优化。
Culler 定律

RAM 不总是 RAM。由于 TLB 缓存的存在,随机访问大范围内存可能导致严重的性能损失。