操作系统笔记(8)-多级页表
操作系统笔记(8)-多级页表
简介
假设一个
32
位地址空间(2^32 字节),4KB
(2^12 字节)的页大小和4B
的页表项大小,那么每个进程需要用来维护页表的内存就是4 * 2^20B
也就是4MB
,当多个进程运行时,页表占用的空间就会非常大!为了解决这个问题,提出了
多级页表
,它的思想是将页表分成页大小
的单元
,如果一整块单元
的页表项无效,就完全不分配该页的页表,为了追踪页表的页是否有效,引入了一个新的数据结构叫页目录(PD)
,它可以告诉你页表的页在哪里或者页表的整个页不包含有效页可以看到,
多级页表
的工作方式就是让线性页表的一部分消失(因为实际运行的程序中可能会有很多单元无效),就相当于将原来的一大张页表拆分成很多小的,用一个页目录
来映射这些小页表
,如果某个小页表中的所有项都是无效的,就不分配这页的内存,如下图所示:上图就是
二级页表
结构,每一个有效
的页目录项(PDE)
都对应这一张含有效
页表项的页表,可以大大节省空间,但是这样会产生额外的内存引用开销,因此多级页表
是一个时间——空间折中
详细示例
设想一个大小为
16KB
的地址空间,其中包含64B
的页,因此我们有14
位(2^14 = 16KB)的虚拟地址空间,其中6
位表示偏移量(2^6 = 64B),剩余8
位表示页号VPN
如果不使用
多级页表
,我们的页表有2^8 = 256
项,假设页表项PTE
的大小为4B
,则页表的大小为256 * 4B = 1KB
使用
多级页表
,我们就需要将页表划分为若干单元
,1KB
的页可以分为16
个64B
的页,每页可以容纳16
项PTE
划分依据,根据单页的大小划分,划分出的每页大小为
64B
,可以容纳64 / 4 = 16
项,因此原页表为划分成了256 / 16 = 16
块单元
,这样就确定了页目录(PD)
结构的大小,如果页目录项PDE
的大小也是4B
,那么PD
的大小刚好为一页的大小为了通过虚拟地址确定页目录项以及页表偏移,我们把
VPN
的8
再划分,前4
位表示页目录索引,后4
位表示页表索引,如下图:假如地址空间中只有前两项和后两项被使用,那么我们只用创建两张页表和一张页目录,相比于原来的
单级页表
,多级页表
大大节省了内存空间
超过两级
- 拿现在最常见的
64
位机器来说(2^64 字节的地址空间),如果页表的大小为4KB
,那么偏移量占12
位,剩余52
位为VPN
,此时如果使用两级页表,页表项大小为4B
,则一张页表可以容纳1024
项,需要的页表索引就是10
位,但是这样页目录索引就占了42
位,页目录需要的大小就是2^42 * 4 B
,太大了完全不可行,因此我们需要对页目录再进行划分,按每个子目录表的大小为4K
来算,需要进行4
级划分(2^40),前面还有2
位就不用了,4
级页表可以将内存消耗控制在一个合理的大小
反向页表
有些系统使用了
反向页表
,即保留一个页表,其中的项代表系统的每个物理页
,而不是每个进程一个的页表页表项告诉我们哪个进程正在使用此页,以及该进程的哪个虚拟页映射到此物理页,因此是
反向
的,由于物理地址非常大,所以线性扫描页表不合理,所以采用了散列表
的方式快速查找
将页表交换到磁盘
- 尽管使用
多级页表
减少了内存消耗,但是它仍然有可能是太大而无法一次装入内存,因此一些系统将这样的页表放入内核虚拟内存,从而允许系统在内存压力较大时,将这些页表中的一部分交换到磁盘