二级页表
一级页表相当于把一本书缩小成几页的目录,通过目录来找书的内容。
但有个问题,如果书非常非常厚,有两本康熙字典那么大,目录也非常多,有一本高中教材那么厚。
那自然而然的,继续分呗,把高中教材那么厚的一级目录就当成一本教材书,再建立一次目录
二级页表由此诞生,就是把页表当数据,再建立页表
案例:
400MB的游戏程序载入了内存
32位系统,块大小固定为4K
则低12位一定是对应块大小的,高20位用于页表索引
400MB/4KB = 100K条,100K条索引,但页表的100K条中,每条32位占4B,所以页表总共就占了4B*100K=400KB的空间
那这400KB的页表也是要放在内存中的,内存一块是4KB,则实际在内存中要占用100块,或者叫100页
——————
但是100页有必要一次性装在进去吗?没必要
前面我们说,程序的数据是按需载入内存,不是一股脑全部塞进去,用不到的就先候着。而这100块或者叫100页其实对了400MB全部全部的数据。
正确的应该是先载入40MB数据,加载到某个地方还需要另外200M数据,再把200MB载入内存
而载入40MB的时候,需要载入总共100页中的10页,同理,再需要另外200MB时候,再对应载入50页。以此节省内存空间
——————
但是如何知道引入100块中的那几块呢?
有点递归的思想,把这100块页表数据看成另外某个程序的空间,也就是一个要占用400KB的程序。
400KB的程序,每块4KB,400KB/4K = 100条,100条索引每条32位占4B,所以页表(这里是页表的页表了)总共需要占用100*4B = 400B空间
400B作为页表也是要占空间的,一块是4KB,它只占了400B,也就是只占了一个最小单位 页的仅仅十分之一空间
——————
对比一下原来400MB的页表占用100页
现在400K(100页)的页表占用0.1页
好了,在极端情况下,32位操作系统内存最大4GB
4000MB的内存占满的情况下,页表占用1000页
4000KB(上面页表的1000页)的页表占用1页(刚刚好1页 4KB大小)
所以采用对页表再分页表的方法,撑死,在内存装满的情况下,顶级页表只需要占用1页而已。
这样,我们可以先把顶级页表全部装入,也就只占1页(一般都装不满),如有需要,再通过顶级页表按需载入二级页表,通过二级页表再引入程序的内容,这样就节省了不少空间
————————————
拓展到64位操作系统
64位,块大小依然是4KB
64位的低12位仍然不懂,对应4KB块大小。那高52位如何划分呢?
此时页表项因为不再是32位,一条占4B了,而是64位系统,页表的一条占用了8B
那么页表占用空间是:想要最多只用1页装入,4KB/8B = 2的9次幂,即为9位。因为妄想着最多只用1页索引,那么不可避免的就要反复建立多级页表了
最终就是:64=12+9+9+9+9+9+7
可以看到最终是6个级别的页表才分完
最后的7是没办法的事情,没有32位的极端情况下那么好运刚刚好只占1页