之前的文章里总结起来就是CPU通过页部件的“三步曲”完成虚拟地址到物理地址的转换关系。
即从CPU的视角是:
第一步:取虚拟地址的高10位,得到页表首地址;
第二步:取虚拟地址的中10位,得到物理页地址;
第三步:将虚拟地址中的低12位与物理页地址合并,即为最终的物理内存地址。
我们正是利用这种“呆板”机制实现虚拟地址访问页表。即,每一个虚拟地址的转换必须经过这三步。
比如如何实现利用虚拟地址访问页目录项(页表首地址)?
分析:虚拟地址的结构是不变的,所以我们必须在第二步得到的物理地址还是页目录的首地址。而我们的页目录首地址是存在页目录项的最后位置。所以我说这里是循环访问自己,不知道你能否理解?
答:虚拟地址高10全为1,则CPU在通过页部件转换时,第一步去页目录中定位到最后一项,CPU认为这就是页表首地址了。(但是这里被我们人为安排的地址是页目录自己的)。
CPU傻乎乎的拿着第一步得到的物理地址(页目录首地址),又取了虚拟地址的中间10位,又是全1,则又定位到最后一项。(这里的结果还是页目录首地址。这不就是循环嘛)但是CPU可不这么认为,他觉得经过前两步,我已经成功得到物理页地址了。
CPU说是时候完成地址转换任务了,来人,将第二步结果的物理页地址给我和虚拟地址的低12位合并。随后CPU毕恭毕敬的给老大(也就是作者本人)报告:我已经完成虚拟地址转换了,请您过目。
老大我一看,虚拟地址0xffff_f000 转换成0x10_0000的物理地址。这物理地址就是我页目录首地址啊。甚好甚好。以后我只要给出0xffff_fxxx格式的虚拟地址,CPU就会访问页目录所在的内存区域。
再进一步,如何利用虚拟地址访问页表项(物理页首地址)呢?
分析:其实CPU通过三步曲就可以得到物理项的地址。这里只希望通过三步曲只得到物理页地址。说明是慢一步。有意为之的慢一步。如何实现呢?
答:多在页目录表里溜达一次。即高10位全给1,则第一步又回到页目录首地址里。原本按照正常计划,第一步就搞到页表地址,第二步搞得物理页地址。现在因为高10位全为1,第一步搞的还是页目录地址,所以第二步只能搞到页表首地址,那么第三步只能在页表里寻址了,得到的自然只能是物理页首地址了。
这时候我们在回到如何访问页目录项(页表首地址)?
其实本质就是慢两步,让第二步结束了得到的地址还是页目录首地址,那么第三步也只能在页目录查询了,得到的也只能是页表首地址了。