四级页表通俗讲解与实践(以 64 位 ARM Cortex-A 为例)


📖

🎥 B 站博文精讲视频:点击链接,配合视频深度学习


四级页表通俗讲解与实践(以 64 位 ARM Cortex-A 为例)

本文面向希望彻底理解现代 64 位架构下四级页表的开发者,结合 ARM Cortex-A 系列处理器,详细讲解虚拟地址到物理地址的映射全过程。结构清晰,细节完整,结合真实虚拟地址与物理地址举例,适合学习与实践。


一、四级页表是什么?

1. 概念引入

  • 在现代 64 位处理器(如 ARMv8-A Cortex-A 系列)中,内存管理单元(MMU)将 虚拟地址(VA) 转换为 物理地址(PA)
  • 为了高效管理大空间内存,ARMv8-A 采用四级页表结构,层层映射。
  • 页表本质是多级查找的"索引表",每一级根据虚拟地址的一部分找到下一级页表或物理页框。

2. 四级页表的结构

  • 每一级页表存放固定数量的表项,每个表项保存下一级页表的物理基地址及权限/属性等。

  • 常见配置下:

    • 每级索引 9 位,512 个表项(2⁹ = 512)
    • 最后 12 位为页内偏移(支持 4KB 页大小)
  • 总共:9 + 9 + 9 + 9 + 12 = 48 位虚拟地址

    LVL0 LVL1 LVL2 LVL3 Offset
    9bit 9bit 9bit 9bit 12bit
    <---------- 48 位虚拟地址 ------------>
  • 在 ARM 文档/代码中,四级页表常称为:

    • Level 0 table(L0)
    • Level 1 table(L1)
    • Level 2 table(L2)
    • Level 3 table(L3)
    • 每一级页表项均为 8 字节(64 位),其中高位用于存储下一级物理基地址。

二、虚拟地址如何拆分?(以 Cortex-A 64 位为例)

假设一个 48 位虚拟地址:

复制代码
0x0000_1234_5678_9ABC

拆解如下:

位段 位数 含义 示例值
47 ~ 39 9 L0 索引(表项) 0x0000000000000002
38 ~ 30 9 L1 索引 0x0000000000000046
29 ~ 21 9 L2 索引 0x00000000000000B0
20 ~ 12 9 L3 索引 0x0000000000000123
11 ~ 0 12 页内偏移(4KB 页) 0x00000000000009ABC

(示例值以实际拆分得到的二进制高/低位为例,便于理解)


三、查表过程:虚拟地址到物理地址的详细流程

1. 分解虚拟地址

  • 每一级用虚拟地址的 9 位做索引,查找该级表的第 N 项。
  • 最后 12 位为页内偏移。

2. 四级查找过程(ARM 通用流程)

  1. L0 表基地址(由 TTBR0/TTBR1 寄存器给出,物理地址)
  2. 用 L0 索引查表,得到 L1 表物理地址(通常 4KB 对齐)
  3. 用 L1 索引查表,得到 L2 表物理地址
  4. 用 L2 索引查表,得到 L3 表物理地址
  5. 用 L3 索引查表,得到最终物理页框地址(高位)
  6. 用页内偏移补齐低 12 位,拼出完整物理地址

3. 图示结构

复制代码
VA [47:39] [38:30] [29:21] [20:12] [11:0]
   |       |       |       |      |
   v       v       v       v      v
 +-------------------------------------------------+
 |   L0   |   L1   |   L2   |   L3   |   Offset    |
 +-------------------------------------------------+

四、完整举例:Cortex-A 64 位四级页表查找过程

例子设定

假设有如下参数:

  • TTBR0_EL1 = 0x4000_0000(L0 页表物理基地址)
  • 虚拟地址 VA = 0x0000_1234_5678_9ABC
1. 拆分虚拟地址
  • L0 索引 = (VA >> 39) & 0x1FF = (0x0000_1234_5678_9ABC >> 39) & 0x1FF = 0x2
  • L1 索引 = (VA >> 30) &
    F = (0x0000_1234_5678_9ABC >> 30) & 0x1FF = 0x46
  • L2 索引 = (VA >> 21) & 0x1FF = (0x0000_1234_5678_9ABC >> 21) & 0x1FF = 0xB0
  • L3 索引 = (VA >> 12) & 0x1FF = (0x0000_1234_5678_9ABC >> 12) & 0x1FF = 0x123
  • Offset = VA & 0xFFF = 0x9ABC
2. 查找过程
  • Step 1:L0(TTBR0_EL1 + 2 × 8)

    • L0表的第2项,假设内容为 0x0000_6000_0003 (L1表物理基地址 0x6000_0000)
  • Step 2:L1(0x6000_0000 + 0x46 × 8)

    • L1表的第70项,内容为 0x0000_7F00_0003 (L2表物理基地址 0x7F00_0000)
  • Step 3:L2(0x7F00_0000 + 0xB0 × 8)

    • L2表的第176项,内容为 0x0000_9000_0003 (L3表物理基地址 0x9000_0000)
  • Step 4:L3(0x9000_0000 + 0x123 × 8)

    • L3表的第291项,内容为 0x0000_A200_3003 (物理页框基地址 0xA200_3000)
  • Step 5:加上 offset

    • 物理地址 = 0xA200_3000 + 0x9ABC = 0xA200_CABC
3. 总结查表过程
  • 虚拟地址 VA = 0x0000_1234_5678_9ABC
  • 物理地址 PA = 0xA200_CABC
  • 每一级查表都用虚拟地址的 9 位,+ 8 字节(64 位表项大小)
  • 终极目标:虚拟地址的页内偏移直接对应物理地址的低 12 位,高位来自页表递归查找结果。

五、总结与实战要点

  • 四级页表让大内存空间管理变得高效且灵活,支持细粒度权限和属性控制。
  • 只要搞懂"每一级 9 位索引 + 最后 12 位偏移",四级页表的本质其实非常直观。
  • ARM Cortex-A(v8 64 位)架构四级页表结构和 x86_64 类似,易于类比和移植理解。
  • 实际开发中,如需分析虚拟地址映射,结合 TTBR0/TTBR1、页表物理地址、虚拟地址拆分即可快速定位。

小结:四级页表是一种多级查找机制,核心在于"索引分段 + 递归查表",只要学会虚拟地址的二进制拆分与索引对应,每一级表项的物理地址拼接,配合工具观测,就能轻松掌握虚拟到物理的完整映射流程。


视频教程请关注 B 站:"嵌入式 Jerry"

相关推荐
是乐谷5 分钟前
饿了么招java开发咯
java·开发语言·人工智能·程序人生·面试·职场和发展
zhysunny5 分钟前
20.万物皆可变身术:状态模式架构全景解析
java·状态模式
hongjunwu9 分钟前
Java集合的遍历方式(全解析)
java·开发语言·windows
cccc来财22 分钟前
Golang的本地缓存freecache
java·开发语言·jvm
ALLSectorSorft24 分钟前
定制客车系统票务管理系统功能设计
linux·服务器·前端·数据库·apache
Barcke29 分钟前
缓存界的 "双保险":打工人救星来了!(本地缓存 + Redis 双剑合璧,轻松应对高并发)
java·后端
用户849137175471631 分钟前
JDK 17 实战系列(第5期):开发工具与API增强详解
java·jvm·架构
嵌入式×边缘AI:打怪升级日志1 小时前
【无标题】
单片机·嵌入式硬件
草履虫建模1 小时前
RuoYi-Cloud 微服务本地部署详细流程实录(IDEA + 本地 Windows 环境)
java·spring boot·spring cloud·微服务·云原生·架构·maven
三次拒绝王俊凯1 小时前
用生活日常的案例来介绍“程序运行时,对函数的调用一般有两种形式:传值调用和引用调用 和 这两种调用有什么区别?
java·数据结构