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结构体。
关键理解:页框是物理内存的“砖块”,页面是虚拟地址空间的“砖块”。页表的作用就是将虚拟页面映射到物理页框上。
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 物理页框。
块映射(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 页面
3.5 小结:四个概念的内在联系
页框、页表项、页表层级与页面大小并非孤立概念,它们共同构成了 ARM64 地址转换的完整数据路径:
- 页面大小决定了虚拟地址中页内偏移的位数,进而影响每级索引的位数和页表层级总数。
- 页表层级定义了地址转换的遍历路径,每级页表由多个 PTE 组成。
- PTE 中的输出物理地址字段指向一个 页框(或下一级页表页框)。
- 页框是物理内存的最终落脚点,其大小必须与页面大小一致。
一句话总结:页表层级是“目录结构”,PTE 是“目录条目”,页面大小是“条目指向的容器规格”,页框是“物理仓库中的货架”。理解这四者的关系,就掌握了 ARM64 地址转换的静态骨架。