这里写个往期推荐,这样可以来回跳跃(狗头
0x00-环境准备
0x01-BIOS以及MBR
0x02-MBR支持显卡
0x03-MBR操作硬盘以及Loader
0x04-进入保护模式
0x05-内存容量检测
0x06-实现内存分页
0x00 基础知识
今天我们来讲解分页的知识,这段知识在学习操作系统和计算机组成原理的时候都是个重要考点哩,但是其中也只讲了些计算方法,今天咱们就来把他实现。
1.虚拟地址
在之前我们检测了咱们的内存地址,发现只有512MB,但是我们的操作系统是基于32位的,所以按道理来说最大寻址空间应该是4GB,难道说我们程序若是放到高于512MB就无法运行了吗,事实上咱们这个4GB寻址范围和内存地址512MB并不是得一一对应,这里直接给大家讲结论,若是想要知道细节的话只需要去翻翻计算机组成原理这本书就行了。也就是说我们的程序最开始是希望加载在一个4GB的广阔大地中的,而加载到哪儿是我们链接器来决定的,实际上也就是程序员自行抉择。但是真正物理机上并不存4GB,所以我们将整片程序中的一部分称为页,然后我们按照自己的需要映射到真实的物理内存当中,此时我们并不需要一次性全部放到物理内存当中。
此时形成的效果就是,咱们在咱们自以为的空间里面是连续的,,而映射到物理内存中是由操作系统决定的,此时就并不一定连续,但我们程序进行的一系列操作都是基于我们自认为的虚拟空间的,操作系统只需要负责映射就行。下面为大家解释一级u页表。
2.一级页表
在我们没有使用分页机制的时候,我们采用的仍然是系统自带的分段方式,也就是依靠段地址:段内偏移来进行地址选择,且该地址仍然是物理地址,寻址过程如图:
而我们开启分页机制之后,我们程序员所使用的地址就变为了虚拟地址,然后我们的寻址过程就变成如下图:
我们使用4GB虚拟内存,首先会将其分为大小一致的一堆页,而这个页面大小一般定为4KB,也就是说在32位地址中,高20位为页地址,而低12位为页内地址.在我们本来的程序中是进行了分段的操作,但是载入物理内存的过程中就会进行分页而打乱顺序,此时就需要用到页表,也表中保存的也就是一个个映射,保证你按顺序访问虚拟地址,他会给出想对应的物理地址。
所以我们就需要一个页表来建立这层映射关系,也表中每个页表项就保存着一个真实物理地址。但是光有页表还不行,我们还需要找得到他,所以我们还需要一个额外的寄存器来保存这个页表在物理地址中的位置。这个寄存器就是控制寄存器CR3.
这里为了防止大家看蒙,我来梳理一下寻址过程:
首先我们拥有想要访问的虚拟地址
此时我们取虚拟地址的高20位,这就是页表相对偏移
我们找到cr3寄存器中的页表首地址,然后加上我们刚刚取到的偏移再乘上4,(这是因为一个页表项占4字节),我们访问该物理地址就会得到另一个物理地址
刚刚从页表当中得到的物理地址是我们真正想要访问的页地址,此时我们再加上虚拟地址的低12位,也就是页内地址,这样我们就得到了我们真正想访问的地址了。
3.二级页表
二级页表同一级页表类似,就是中间又加了一层而已,这里提出二级页表的原因是由于最高级页表必须在内存,但是我们若只采用一级的话,常驻内存的页表会十分巨大,所以我们需要再加上一级页表(这里应该被叫做页目录)用来减少内存消耗,我们在一级页表是采用了高20位来表示页表项的便宜,这里我们二级页表将其对半分开,高10位用作页目录偏移,剩下的10位用作页表偏移。分配情况如下图所示:
其中页目录项之于页目录,页表项之于页表,就如同段描述符之于全局描述表一样,下面给出这俩的具体结构:
支付3UD,阅读全文
还有更多的精彩内容,作者设置为付费后可见