多级页表为什么存在
理解页表之后,一个很自然的问题就是:
页表本身会不会太大?
这正是多级页表要解决的问题。
一、单级页表为什么会太大
页表的作用是记录虚拟页到物理页框的映射关系。理论上,虚拟地址空间里的每个虚拟页都需要对应一个页表项。
所以虚拟页越多,页表就越大。
以 32 位系统为例,如果:
- 虚拟地址空间是 4GB
- 页大小是 4KB
那么虚拟页数就是:
4GB / 4KB = 2^20
如果每个页表项占 4 字节,那么一个进程的单级页表就大约需要 4MB。
这说明:
仅页表本身,就可能占用不小的内存。
二、问题不只是“大”,而是“很多根本用不到”
更关键的是,进程虽然理论上拥有很大的虚拟地址空间,但实际真正使用的通常只是一部分。
比如:
- 少量代码页
- 少量数据页
- 当前栈和堆使用到的那部分页
- 若干映射区
大量虚拟地址根本没有被映射,也没有被访问。如果仍然为所有虚拟页都准备页表项,就会造成大量浪费。
三、多级页表的核心思想
多级页表的核心思想是:
不一次性把整张大页表都建出来,而是分层并按需创建。
也就是说:
- 顶层先作为目录存在
- 只有某片地址区域真正被使用时,才创建它对应的下一级页表
- 没用到的大片地址区域,对应的下级页表根本不用分配
这样就能显著节省页表内存。
四、如何理解“按需创建下级页表”
可以把多级页表想成一棵树,而不是一张平铺开的巨大表。
如果某片虚拟地址范围从来没有被用到,那么:
- 顶层对应表项为空
- 下级页表根本不存在
只有当这片地址第一次真正需要建立映射时,操作系统才会:
- 分配一块内存作为下级页表
- 更新上一级页表项,让它指向新建的下级页表
所以多级页表的关键收益,不只是“能查”,而是:
按需分配页表空间,不为未使用的地址区域浪费整张下级页表。
五、两级页表怎么理解
两级页表可以理解为:
- 第一级:页目录
- 第二级:具体页表
地址转换时,大致流程是:
- 用高位索引查页目录
- 找到对应二级页表
- 再用中间部分查具体页表项
- 最后结合页内偏移得到物理地址
你可以把它想成“先查目录,再查正文”。
六、多级页表节省了什么
多级页表节省的不是页本身的数据空间,而是:
页表作为映射结构所占用的内存空间。
如果某个进程只用了很小一部分虚拟地址空间,那么很多下级页表都不需要创建。这比单级页表一次性准备完整大表要节省得多。
七、多级页表的代价是什么
多级页表的主要代价是地址转换路径更长。
TLB 命中时,这种开销通常被掩盖;但一旦 TLB 未命中,就必须层层回退去查页表,访问链路会明显变长。
因此:
多级页表越深,越依赖 TLB 去隐藏查表成本。
八、为什么 64 位系统更需要多级页表
64 位系统的虚拟地址空间远大于 32 位,如果还坚持使用单级页表,页表规模会非常夸张。
所以在 64 位系统中,多级页表几乎是必然的。常见系统里会看到四级页表甚至五级页表结构,本质上都是为了解决大地址空间下页表本身过大的问题。
九、总结
多级页表存在的根本原因,是单级页表在大地址空间下过大,而且会为大量未使用的虚拟地址空间白白浪费页表项。多级页表通过把页表分层,并且按需创建下级页表,只为真正使用到的地址区域分配页表空间,从而显著节省页表内存。它的代价是地址转换路径更长,因此更依赖 TLB 来加速。
