3. 页表项结构详解:PTE 的典型字段

页表项(Page Table Entry, PTE)是虚拟内存映射的核心数据结构,每个 PTE 对应一个虚拟页到物理页的映射关系。PTE 中不仅包含物理页框号(PFN),还包含一组权限位和状态位,用于控制对该页的访问方式、缓存策略以及记录页面的使用状态。本章详细解析 PTE 的典型字段及其在操作系统内核中的实际作用。

学习提示:PTE 的位布局因体系结构而异(x86-64、ARMv8-A、RISC-V 各有差异),但核心字段语义高度一致。理解这些字段的通用含义后,迁移到具体硬件平台只需查阅对应手册即可。

3.1 PTE 整体结构概览

一个典型的 64 位 PTE 由高位到低位依次包含:保留位/软件可用位、物理页框号(PFN)、以及一组权限/状态标志位。下图展示了一个标准 64 位 PTE 的位域布局:

64位页表项(PTE)位域布局 64位页表项(PTE)位域布局 保留/软件 物理页框号(PFN) 标志位组(Flags) 63:52 51:12 11:0 P R/W U/S D A 其他 bit 0 bit 1 bit 2 bit 6 bit 5 bits 3,4,7-11 P=Present, R/W=Read/Write, U/S=User/Supervisor, D=Dirty, A=Accessed
关键理解:PTE 的位域设计体现了硬件与操作系统的分工——PFN 提供映射地址,标志位提供权限与状态约束,保留位则留给操作系统软件自定义用途(如页换出标记、NUMA 信息等)。

3.2 核心字段详解

3.2.1 Present 位(存在位)

Present 位(通常为 bit 0)指示该页表项对应的虚拟页是否当前驻留在物理内存中。这是 MMU 进行地址转换时检查的第一个条件。

  • P=1:页在物理内存中,MMU 正常进行地址转换。
  • P=0:页不在物理内存中(已被换出到磁盘,或尚未分配),MMU 触发缺页异常(Page Fault),由操作系统内核处理。
避坑指南:当 P=0 时,PTE 中的其他位(包括 PFN)对 MMU 而言是无效的。操作系统通常利用 PFN 字段存储页在交换文件中的偏移量或磁盘块号,这称为“交换条目(Swap Entry)”复用技术。

3.2.2 Read/Write 位(读写权限位)

R/W 位(通常为 bit 1)控制对该页的写操作权限。该位与处理器当前运行的特权级协同工作。

R/W 位 处理器模式 允许操作 典型场景
0 用户态(Ring 3) 只读 代码段、只读数据段
0 内核态(Ring 0) 读写(x86 上内核可写只读页) 内核访问用户代码段
1 用户态 读写 堆、栈、数据段
1 内核态 读写 内核数据区
实现细节:在 x86 架构中,当 R/W=0 且处理器处于内核态时,仍然允许写入——这是“只读页”在内核视角下的例外。ARMv8-A 则通过独立的 AP[2:1] 位更精细地控制 EL0/EL1 的读写权限。

3.2.3 User/Supervisor 位(用户/超级用户位)

U/S 位(通常为 bit 2)区分该页是用户态可访问还是仅内核态可访问。这是用户态与内核态隔离的关键机制。

  • U/S=0(Supervisor):仅内核态(Ring 0/EL1/S-mode)可访问,用户态访问触发权限异常。
  • U/S=1(User):用户态和内核态均可访问。

操作系统利用该位保护内核代码和数据段不被用户程序破坏。用户程序试图访问 U/S=0 的页时,MMU 直接拒绝并触发异常,无需软件干预。

3.2.4 Dirty 位(脏位)

Dirty 位(通常为 bit 6)由 MMU 硬件在第一次对该页执行写操作时自动置 1,表示该页的内容已被修改,与磁盘上的备份副本不一致。

  • D=0:页未被写入过,内容与磁盘副本一致(干净页)。
  • D=1:页已被写入,内容已修改(脏页),换出时必须写回磁盘。
性能优化:操作系统在换出页时,只将 Dirty=1 的页写回磁盘;Dirty=0 的页可以直接丢弃或重用,无需 I/O 操作。这显著减少了交换开销。

3.2.5 Accessed 位(访问位)

Accessed 位(通常为 bit 5)由 MMU 硬件在第一次对该页进行读或写操作时自动置 1,表示该页最近被访问过。

操作系统利用 Accessed 位实现页面置换算法(如 Clock/第二次机会算法):

  1. 定期扫描页表,检查 Accessed 位。
  2. 若 A=1,则置为 0 并继续保留该页(给予“第二次机会”)。
  3. 若 A=0,则该页是候选换出页。
注意:Accessed 位由硬件置位,但必须由操作系统软件清零。硬件不会自动清零 Accessed 位,这是操作系统的职责。

3.2.6 Page Frame Number(物理页框号)

PFN(也称为物理地址高位域)是 PTE 中最重要的地址字段,存储物理内存页框的基地址(高位)。MMU 将虚拟地址的页内偏移与 PFN 拼接,形成完整的物理地址。

PFN 的位宽取决于物理地址空间大小和页大小:

体系结构 页大小 物理地址宽度 PFN 位宽
x86-64(4KB 页) 4 KB 48 位(52 位扩展) 36 位(40 位)
ARMv8-A(4KB 页) 4 KB 48 位 36 位
RISC-V Sv39 4 KB 56 位 44 位

3.3 字段组合与权限检查流程

MMU 在地址转换时,按固定顺序检查 PTE 字段,任何一步失败都会触发异常。下图展示了完整的权限检查流水线:

MMU 页表项权限检查流程 MMU 页表项权限检查流程 ① 检查 Present 位 P=0 → 触发缺页异常 P=1 → 继续检查 ② 检查 U/S 位 用户态 & U/S=0 → 权限异常 ③ 检查 R/W 位 写操作 & R/W=0 → 写保护异常 ④ 通过 → 地址转换 检查顺序:Present → U/S → R/W,任一失败即触发对应异常,不继续后续检查

3.4 其他常见标志位

除上述核心字段外,不同体系结构还定义了若干辅助标志位:

标志位 典型位置 含义 典型用途
PWT (Page Write-Through) bit 3 页级写透缓存策略 控制该页的缓存写策略(透写/回写)
PCD (Page Cache Disable) bit 4 页级缓存禁用 用于设备 I/O 内存映射页,禁止 CPU 缓存
PAT (Page Attribute Table) bit 7 页属性表索引(x86) 扩展内存类型控制,与 PWT/PCD 组合使用
G (Global) bit 8 全局页标志 防止 TLB 刷新时清除该页(如内核空间常驻页)
NX (No-Execute) bit 63 不可执行位 禁止在该页上执行代码(DEP/NX 保护)
安全意义:NX 位是现代操作系统实现数据执行保护(DEP)的硬件基础。将栈、堆等数据页标记为 NX=1,可有效阻止缓冲区溢出攻击中的代码执行。

3.5 软件可用位与内核复用

PTE 的高位(如 x86-64 的 bits 63:52)通常被标记为“软件可用”(Software Available),操作系统内核可以自由写入自定义数据。常见复用场景包括:

  • 页换出标记:当 P=0 时,PFN 字段被复用为交换文件偏移量,软件可用位存储换出状态。
  • NUMA 节点 ID:记录该页所属的 NUMA 内存节点,用于内存亲和性调度。
  • 引用计数/年龄:辅助页面置换算法记录页面的访问频率或老化信息。
  • KSM (Kernel Same-page Merging) 标记:标识该页是否参与内核同页合并。
内核实现参考:Linux 内核在 include/linux/pgtable.h 和体系结构相关的 arch/x86/include/asm/pgtable_types.h 中定义了 PTE 位域的操作宏,如 pte_present()、pte_mkdirty()、pte_wrprotect() 等。

3.6 本章小结

PTE 的每个字段都经过精心设计,在硬件效率与软件灵活性之间取得平衡:

  • Present 位是地址转换的“开关”,控制页是否在内存中。
  • R/W 和 U/S 位构成两级权限模型,实现用户态/内核态隔离与读写保护。
  • Dirty 和 Accessed 位由硬件自动维护,为操作系统提供页使用状态信息,支撑换出策略。
  • PFN 是映射的核心,将虚拟页绑定到物理页框。
  • 辅助标志位(PWT、PCD、NX、G 等)提供细粒度的缓存、执行和 TLB 管理控制。