接下来我们讲快表和多级页表
那在刚才我们说
快表是利用缓存的机制
来减少对内存的访问
而多级页表 是通过间接引用的方式
来减少页表的长度
那么它们具体怎么做的呢
快表实际上就是把近期访问过的页表项
缓存到CPU里头
底下是我们在前面没有使用快表的时候
正常情况下 你获取物理页号的过程
逻辑页号在内存当中去查页表
找到物理页号 然后得到物理地址
那现在在这里缓存之后怎么办呢
我在CPU里头 加上一组关联存储器
关联存储器是什么呢
关联存储器是说我这里有一个key
我进来之后它可以并行的
同时查所有的这些表项
有匹配的 把匹配的找出来
那你说这里
原先在内存里访问一次你觉得费事
到这里来你访问这么多次
它就不费事吗
实际上在这里头呢
由于是在CPU里头
它的速度会很快
当然由于它的速度快 成本高 功耗大
所以这个地方不能做的很大
如果说匹配得上
那这时候呢它直接得到它的物理页号
也就相当于我逻辑页号作为key
找到它的物理页号
那我就得到你的物理页号
这就不需要到内存当中访问了
如果说在这里头你找的时候
因为你这里容量很小
肯定没有办法把整个页表
全部装到这个CPU里头去
好 那这些有不命中的
那不命中的时候呢
它就会从这儿
你得再去找内存当中的页表
这时候你只能是两次访问了
好 找到这个页表之后呢
我得到它的页帧号
同时我把这个内容
再缓存到CPU里的快表里头去
下次再访问这一页里的数据的时候
你就不必要再去访问内存了
好 如果说我们在这里头
99%的访问我都是在这个TLB里
快表里命中的
那只有一次1%
是要到物理内存当中去查页表的
这时我们的性能就能大幅度提高
这是快表的基本原理
好 接下来我们介绍多级页表
多级页表是通过间接引用
将页号分成若干级
比如说在这里头
我们原来的逻辑地址的格式
是页号加页内偏移
现在变成了三级页号
P1 P2 P3 然后再加上页内偏移
和它相对应的 我们的页表呢
也会因此而形成一个树状结构
比如说原来一张大的线性页表
我把它切成若干段
这切到段的个数呢
和你最后一级页表的宽度是一致的
然后它每一个子页表的起头呢
作为上一级页表的物理页号
填到上一级页表当中
在第二级的页表的宽度
和你第二级页号的宽度是一致的
然后再一个 第二级页表的起头
再作为第一级页表项的物理页号
那这时候它的项数
和你第一级页表的宽度是相一致的
在这种情况下
我们要访问相应的物理内存单元
那怎么访问呢
是从第一级查第二级 再查第三级
那这时候我们整个访问次数就是K+1
你这里是三级 那就是四次
具体的访问过程是这样的
第一级作为第一级页表的偏移
找到第二级页表上的起始
第二级页表项
再作为在第二级页表当中的偏移
加在一起找到第三级页表项的
起始页号 物理页号
然后这地方呢 这一页呢
每一页这些页表都是和页相对齐的
所以从这儿呢它就不再有页内偏移
好 然后从这儿找到
最后的 你要实际访问的
那个内存单元的物理页号
再加上最后一次物理内存的访问
那通过这种方式
我们可以有效地减少每一级页表的长度
那如果说 你是所有的页表项都存在的话
你用多级页表实际上对它的存储并没有减少
但实际上 我们实际运行的进程呢
多数并不会用到整个所有的页表
所有的内存地址空间 逻辑地址空间
在这种情况下
我们可以通过各级页表当中的存在位
把那些不存在的给省掉
如果说我在第一级页表里头
有一个下一块区域都不存在的话
那么这样一来
我节省出来的空间就会大幅度增加
我使用的空间就会大幅度减少
好 用这种方式呢
实际上我们使用多级页表呢
可以有效地的减少页表的大小
下面我们通过一个简单的
但是更具体的例子 二级页表
我们看它是怎么做的
这儿呢我们把20位的地址总线
把它切成了三段
0到10 1K
10位作为页内偏移
然后前面切成两个五位的页号
第一级和第二级
那在实际访问的时候是什么样
这是这里头第一级
那第一级页表的起头在哪呢
它是写到固定寄存器里的
在因特尔的CPU上
有一个叫CR3的寄存器
好 在这个寄存器里头存的起始位置
加上你的第一级的页号
作为它的索引 下标
找到相应的页表项
这是第二级页表的起始页号
好 那第二级页表呢
你找这个起始位置
加上第二级的页表号
把它俩找到你的实际的物理页号
那这时候把偏移直接搬过来
那就得到你的物理地址了
有了这样一种做法呢
我们就可以很方便地
利用多级页表减少你整个页表的长度