x86 32 位分页机制(一级 & 二级页表)详解
在 x86 32 位分页机制(Paging)中,虚拟地址 到 物理地址 需要 页表转换,有两种常见模式:
- 一级页表(4MB 页):直接映射,无需二级页表
- 二级页表(4KB 页):两级转换,细粒度分页
1. x86 32 位的虚拟地址空间
-
虚拟地址(Virtual Address)= 32 位:
[
2^{32} = 4GB
]
CPU 看到的是 4GB 虚拟地址,而不是物理地址,需要页表转换。 -
分页机制的作用
- 让进程有独立的地址空间
- 可以使用比物理内存更大的虚拟内存
- 支持进程间隔离,提高安全性
- 减少碎片,提高内存管理效率
2. 一级页表转换(直接映射 4MB 页)
- 一级页表 = 只用页目录(Page Directory)
- 一个页目录项(PDE)直接映射一个 4MB 物理页
- 无需二级页表
📌 地址划分
| 10-bit 页目录索引 | 22-bit 页偏移 |
---------------------------------
| 10 位 | 22 位 |
- 前 10 位:页目录索引(找到页目录表中的一个 PDE)
- 后 22 位:页偏移(直接在 4MB 页内寻址)
📌 示例
假设虚拟地址:
虚拟地址 = 0x12345678
拆分:
页目录索引 = (0x12345678 >> 22) = 0x48
页偏移 = 0x345678 & 0x3FFFFF = 0x345678
- 先查 页目录表 的第
0x48
项(指向物理地址0x08000000
)。 - 物理地址 =
0x08000000 + 0x345678
。
✅ 直接映射 4MB 大页,不需要二级页表,适用于内核高效映射大块内存。
3. 二级页表转换(4KB 页,常用)
- 二级页表 = 页目录(Page Directory)+ 页表(Page Table)
- 一个页目录项(PDE)指向一个页表(4KB 页表)
- 一个页表项(PTE)指向 4KB 物理页
- 用于常规用户态进程映射,支持更细粒度的分页
📌 地址划分
| 10-bit 页目录索引 | 10-bit 页表索引 | 12-bit 页偏移 |
-------------------------------------------------
| 10 位 | 10 位 | 12 位 |
- 前 10 位:页目录索引(找到页目录表中的 PDE)
- 中 10 位:页表索引(找到页表中的 PTE)
- 后 12 位:页内偏移(在 4KB 页内寻址)
📌 示例
假设 虚拟地址:
虚拟地址 = 0x12345678
拆分:
页目录索引 = (0x12345678 >> 22) & 0x3FF = 0x48
页表索引 = (0x12345678 >> 12) & 0x3FF = 0x15E
页偏移 = 0x12345678 & 0xFFF = 0x678
转换步骤
- 查 页目录表(PDE),找到 第
0x48
项,指向 页表地址0x400000
。 - 查 页表(PTE),找到 页表
0x400000
的0x15E
项,指向 物理页0x8000
。 - 计算物理地址:
物理地址 = 0x8000 + 0x678 = 0x8678
✅ 支持 4KB 精细分页,适合进程映射和内存管理。
4. 对比一级页表和二级页表
方式 | 页大小 | 地址索引结构 | 是否需要二级转换 | 适用场景 |
---|---|---|---|---|
一级页表 | 4MB | 10 位 + 22 位 | ❌ 直接映射 | 内核大块内存映射 |
二级页表 | 4KB | 10 位 + 10 位 + 12 位 | ✅ 两级转换 | 进程内存管理 |
5. 结论
-
x86 32 位支持两种分页模式:
- 一级页表(4MB 大页):直接映射,适合内核大块内存。
- 二级页表(4KB 小页):适用于用户进程,分页更精细。
-
一级页表:10-bit 目录索引 + 22-bit 偏移
-
二级页表:10-bit 目录索引 + 10-bit 页表索引 + 12-bit 偏移
🚀 二级页表更常见,能精细控制内存,但多了一次页表访问(TLB 缓存优化)。 🎯