3、页表基础概念:页框(Page Frame)、页表项(PTE)、页表层级(L0/L1/L2/L3)、页面大小(4K/16K/64K)

页表是操作系统实现虚拟地址到物理地址转换的核心数据结构。在 ARM64 Linux 内核中,页表的设计直接决定了内存管理的效率、TLB 的命中率以及进程隔离的安全性。本节将深入剖析页框、页表项、页表层级与页面大小这四个基础概念,为后续理解地址转换全流程打下坚实基础。

3.1 页框(Page Frame)——物理内存的最小管理单元

页框(Page Frame,也称物理页)是物理内存被划分成的固定大小的连续块。操作系统以页框为单位管理物理内存,每个页框都有一个唯一的编号——页框号(PFN,Page Frame Number)。

  • 页框 vs 页面:页面(Page)指虚拟地址空间中的一块连续区域,而页框指物理内存中的一块连续区域。页框是物理概念,页面是虚拟概念。
  • 大小一致:页面与页框的大小必须相同,通常为 4KB、16KB 或 64KB(ARM64 支持)。
  • 分配与回收:内核通过伙伴系统(Buddy System)管理页框的分配与释放,每个页框对应 struct page 结构体。
关键理解:页框是物理内存的“砖块”,页面是虚拟地址空间的“砖块”。页表的作用就是将虚拟页面映射到物理页框上。
页框(Page Frame)与页面(Page)的对应关系 虚拟地址空间(页面) 页面 0 (VPN=0) 页面 1 (VPN=1) 页面 2 (VPN=2) 页面 3 (VPN=3) 页表映射 物理地址空间(页框) 页框 5 (PFN=5) 页框 8 (PFN=8) 页框 12 (PFN=12) 页框 15 (PFN=15)

3.2 页表项(PTE)——地址转换的原子单元

页表项(PTE,Page Table Entry)是页表中的最小数据单元,每个 PTE 描述一个虚拟页面到物理页框的映射关系。在 ARM64 中,每个 PTE 固定为 8 字节(64 位)。

PTE 的核心字段

位域 名称 说明
[63:48] PBHA / 保留 页属性提示扩展(Page Based Hardware Attributes)或保留位
[47:12] 输出物理地址(PA) 物理页框号(PFN)左移 12 位,指向 4KB 页框基址
[11:10] AP[2:1] 访问权限(Access Permission),控制读/写/执行
[9] SH 可共享性(Shareability),指示内存域(非共享/内部共享/外部共享)
[8:6] AttrIndx 内存属性索引,指向 MAIR 寄存器中的属性配置
[5] NS 非安全空间(Non-Secure),用于 TrustZone 隔离
[4] AF 访问标志(Access Flag),硬件置位表示页面已被访问
[3:2] nG / D / PXN / UXN 非全局位、脏位、特权执行禁止、用户执行禁止
[1] DBM 脏位管理(Dirty Bit Management),用于软件脏页跟踪
[0] Valid 有效位:1=映射有效,0=无效(缺页或未映射)
PTE 大小与页表层级的关系:每个 PTE 占 8 字节,一个 4KB 的页表页可容纳 512 个 PTE(4KB / 8B = 512)。这正是 ARM64 页表层级中每级索引宽度为 9 位(2^9 = 512)的根本原因。

3.3 页表层级(L0/L1/L2/L3)——多级转换的骨架

ARM64 采用 4 级页表结构(L0、L1、L2、L3),以适应 48 位虚拟地址空间(未来可扩展至 52 位)。多级页表的核心优势在于:按需分配——只有实际使用的虚拟地址范围才需要分配页表页,大幅节省内存。

层级结构与索引划分

以 4KB 页面、48 位虚拟地址为例,虚拟地址被划分为 5 个部分:

| 63:48 | 47:39 (L0) | 38:30 (L1) | 29:21 (L2) | 20:12 (L3) | 11:0 (页内偏移) |
| 符号扩展 | 9 位索引  | 9 位索引   | 9 位索引   | 9 位索引   | 12 位偏移      |
  • L0 级:顶级页表,覆盖 512GB 虚拟地址空间(9 位索引 × 1GB 块)。
  • L1 级:第二级,覆盖 1GB 虚拟地址空间(9 位索引 × 2MB 块)。
  • L2 级:第三级,覆盖 2MB 虚拟地址空间(9 位索引 × 4KB 块)。
  • L3 级:最后一级,存放最终 PTE,映射 4KB 物理页框。
ARM64 4 级页表层级结构(4KB 页面) 虚拟地址 (48位) 符号扩展 [63:48] L0 索引 [47:39] L1 索引 [38:30] L2 索引 [29:21] L3 索引 [20:12] 页内偏移 [11:0] L0 页表 512 个表项 L1 页表 512 个表项 L2 页表 512 个表项 L3 页表 512 个 PTE 覆盖 512GB 覆盖 1GB 覆盖 2MB 覆盖 4KB 物理页框

块映射(Block Mapping)与大页支持

ARM64 允许在 L1 或 L2 级使用块描述符(Block Descriptor)直接映射大块内存,跳过后续层级:

  • L1 块:映射 1GB 连续物理内存(仅需一次页表访问)。
  • L2 块:映射 2MB 连续物理内存(对应 Linux 的透明大页 THP)。
性能陷阱:虽然块映射能减少页表层级遍历次数并降低 TLB 压力,但 Linux 内核默认以 4KB 粒度管理内存。启用大页(HugeTLB 或 THP)时需谨慎评估内存碎片与交换开销。

3.4 页面大小(4K / 16K / 64K)——粒度与覆盖范围的权衡

ARM64 架构支持三种页面粒度:4KB、16KB 和 64KB。页面大小直接影响页表层级数、单级覆盖范围以及 TLB 的利用效率。

三种页面粒度的对比

参数 4KB 页面 16KB 页面 64KB 页面
页内偏移位数 12 位 14 位 16 位
每级索引位数 9 位 11 位 13 位
页表层级数 4 级 (L0-L3) 3 级 (L0-L2) 2 级 (L0-L1)
单级 PTE 数量 512 2048 8192
L0 覆盖范围 512 GB 64 TB 256 TB
TLB 单表项覆盖 4 KB 16 KB 64 KB
典型应用场景 通用 Linux 发行版 存储服务器、数据库 高性能计算、网络设备

Linux 内核的选择

Linux 内核在 ARM64 平台上默认使用 4KB 页面,原因如下:

  • 兼容性:4KB 是 x86、ARM32 等主流架构的标准页面大小,便于跨平台代码复用。
  • 内存利用率:4KB 小页面减少了内部碎片(Internal Fragmentation),适合通用工作负载。
  • 页表开销:虽然 4KB 需要 4 级页表,但通过按需分配,实际占用的页表内存通常远小于大页面方案。
内核编译选项:在 ARM64 Linux 内核中,可通过 CONFIG_ARM64_PAGE_SHIFT 配置页面大小:
CONFIG_ARM64_PAGE_SHIFT=12 → 4KB 页面
CONFIG_ARM64_PAGE_SHIFT=14 → 16KB 页面
CONFIG_ARM64_PAGE_SHIFT=16 → 64KB 页面
三种页面粒度下的页表层级对比 4KB 页面 4 级页表 L0 (9位) → L1 (9位) L2 (9位) → L3 (9位) 页内偏移: 12位 16KB 页面 3 级页表 L0 (11位) → L1 (11位) L2 (11位) → 物理页框 页内偏移: 14位 64KB 页面 2 级页表 L0 (13位) → L1 (13位) 直接映射物理页框 页内偏移: 16位

3.5 小结:四个概念的内在联系

页框、页表项、页表层级与页面大小并非孤立概念,它们共同构成了 ARM64 地址转换的完整数据路径:

  1. 页面大小决定了虚拟地址中页内偏移的位数,进而影响每级索引的位数和页表层级总数。
  2. 页表层级定义了地址转换的遍历路径,每级页表由多个 PTE 组成。
  3. PTE 中的输出物理地址字段指向一个 页框(或下一级页表页框)。
  4. 页框是物理内存的最终落脚点,其大小必须与页面大小一致。
一句话总结:页表层级是“目录结构”,PTE 是“目录条目”,页面大小是“条目指向的容器规格”,页框是“物理仓库中的货架”。理解这四者的关系,就掌握了 ARM64 地址转换的静态骨架。