1.分页机制存在的问题
实际上分页机制存在问题,所以需要多级页表和快表辅助解决这个问题。
分页机制主要的问题就是页表太大了….
由于要提高内存空间的利用率,分出来的实际物理页应该是很小的(4K),但是页小了相应的页表就会变大。我们需要解决这个问题。
2.方案一,去掉没有记录地址的页号。
按照分页机制,一个程序的段会被分成好多个页。这个页的页号是由这个段的最大逻辑寻址空间决定的。32位系统中,一个程序段的逻辑地址是32位的,所以最大逻辑地址是2的32次方。每个页内存的大小为4K(2的12次方),因此32位逻辑地址空间总共包含2的20次方个逻辑页。每个逻辑页对应一个页号,因此这个程序段的页表的页号数量共有2的20次方,即1M个页表项。而通常一个页表项大小是4B,因此32位下一个程序段的页表会占据4M的内存空间。这是非常大的。
但是实际上一个程序段的逻辑地址根本不会全部用到。事实上也只会用到其中一部分。那么没有用到的页号记录能不能直接删掉呢?我们只保存会用到的地址的页号不行吗?
不行。
这样做的话,页表的页号就不连续了,无法像数组那样通过页号快速找到相应的页记录,即无法进行随机读取了。那么重定位时,我们要想找到对应的物理页框,必须遍历整个页表进行查找,这就需要额外访问内存,花费的时间即使使用二分查找也很慢。
因此页号必须连续。尝试失败。
3.方案二:多级页表
那么我们又要页号连续,又要页表占用内存少,这该怎么办呢?
我们可以类比一下,
看书的时候 如果一本书只有一级目录的话,一般要查半天才能找到我们想要看的节。
比如我要看“多级页表”那一节,我只能从目录头一条条找下去,看到“多级页表”才代表我找到了,然后查找对应的页号,翻到那一页。
但如果有大章的概念,也就是二级目录,就可以很快查找。
还是那本书,如果“多级页表”那一节有一个大章,叫做“内存管理”。那么我先查大章,找到“内存管理”,再在这一章的目录下找“多级页表”这一节对应的目录,这不就快多了吗?
将这个思想应用到页表上,就创建出了多级页表的概念。上边给出的节目录就相当于页表。多级目录就是在节的基础上建立的章,多级页表就是在页表的基础上再建立一个页表,通常称其为页目录。每个页目录包含多个页表项,通常每个页目录包含2的10次方个页表项。一个页表项是4B,因此4M区域是一章,而其中每个4K是章中的节。
多级页表的运作方式:32位的程序段的逻辑地址被分为三段,分别是页目录号(10bits),页号(10bits),以及页内偏移(12bits)。
那么计算物理地址的过程就变成了这样:每次通过页目录号查找到对应的节目录页表,再通过页号找到对应的物理页框。最后加上页内偏移计算出真实的物理地址。
对于多级页表机制,不需要用到的章就不用建立到页表的索引,只是为了查找页表项能够快速放置在那里。而真正用于记录的页表设置到节目录页表的索引。图中这个程序段使用了12M内存,但是这一个二级页表和三个一级页表加起来也只占用了16k的空间。非常节省空间。
4.快表
多级页表提高了空间效率,但是回增加访问内存的次数。因为需要通过页目录号查页表,页表又得查所在页号才能计算实际地址。尤其是64位系统,由于寻址空间增大,这个次数将会更多。
由此产生了快表。
快表TLB是一组相连快速存储,是个寄存器,因为其特殊硬件设计根据页号直接找到相关的页号,再通过页号寻找到页框号。所以页号不用连续,可以支持直接快速查找。
对于最近老是使用的页和对应的页框数据都会被放在快表中查询,操作系统在需要重定位时,会先查询TLB寄存器中的快表,如果快表找不到了,才会去内存中查找多级页表。
TLB这玩意当然越大越好,但是TLB很贵,所以TLB一般的条目数目一般在64~1024之间
快表可以缓解多级页表地址重定位慢的问题。因此多级页表+快表,这就是一种通常的,快速的分页机制。