之二:X86页式内存管理

X86页式内存管理

内存管理的目的是什么?内存管理本身就像一个外观模式,它隐藏底层细节而给应用程序提供一个统一易用的访问内存的接口。程序可以访问4G空间中的任意地址,但实际上物理内存可能只有几百M,这之间的矛盾该怎么解决?关键时刻,还是得抱硬盘的大腿。当可用内存不足时,将内存中不紧急的内容从内存中换出到磁盘上,从而腾出内存给更紧急的程序使用。当需要访问之前的内容时,再将磁盘中数据读入到内存中。内存管理就这样游走在进程的夹缝中,像魔术师一样硬生生的将几百M的内存用出“就像有4G内存一样”的效果。

核心问题来了,内存与磁盘的换入换出,该如何进行呢?显然,为了降低系统的复杂度,每次换入的基本单元其大小最好固定,不能太大,太大则影响换入速度,也不能太小,太小则换入太频繁。

那在段式管理中,该如何操作呢?将整个段一次性换入换出吗?可是每个段的长度不固定呀,而且整个段似乎也太大了。有人会说,段选择符最多支持8192个段(16位段寄存器的高13位用来索引段描述符),将4G的空间分摊到8192个段上,每个段的大小平均512K,可以满足要求了吧,但是CPU中只有6个段寄存器(CS/DS/SS/ES/GS/FS),要访问8192个段,需要频繁的切换段寄存器的内容,这也是一笔不小的开销呀。

为了解决这个问题,intel在386引入页式内存管理管理。由于有向前兼容的包袱,而且内存的“保护模式”也是建立在段式内存管理之上的,intel的页式管理不可能另起炉灶,只能在段式管理的基础上实现。某本书的作者说“加层是解决计算机问题的万金油”(原话可能不是这样),诚不我欺也。在段式内存管理中,访存指令中的“逻辑地址”经过段式转换,变成了发送到地址总线上的“物理地址”,这里加层处理就是:“逻辑地址”经过段式转换后,不再是“物理地址”而是“线性地址”,“线性地址”经过页式内存管理转换后才是最终发往地址总线上的“物理地址”。

页式内存管理中将4GB地址空间分割成4KB大小的页面,每个页面可以映射至内存中任意位置处的4KB物理空间(边界必须与4KB对齐)。在段式内存管理中,连续的逻辑地址映射到物理内存中也是连续的,而在页式内存管理中,连续的线性地址映射到物理内存中就不一定是连续的了,这也正是页式管理的灵活所在。由于页式管理的引入,32位的线性地址有了新的解释,如下:


其中高10位用作目录表索引,一共可以索引1024个目录项,目录项是一个32位的数,其中的高20位指向该目录项对应的页面表。同样页面表中有1024个页面项,每个页面项也是32位的数,其高20位指向物理页面的基地址(边界必须与4KB对齐),由于每个页面有4KB的空间,所以线性地址中的低12位用来表示在页面内的偏移。可见,如果我们可以获取到目录表的基地址,就可以将一个线性地址转换为对齐的物理地址了。刚刚好,intel的CPU中增加了一个寄存器CR3,指向当前页面表的基址。转换过程示意如下:


那么,为什么要分两个层次,先找到目录项再找到页面表,为什么不一步到位直接在页面表中找到对应的页面?这是出于空间效率的考虑。假定一步到位即目录表索引与页面表索引合二为一的话,页面表将有1K*1K=1M个页面表项,其能寻址的范围也是1M*4K=4G,但是考虑到一个进程不可能用到全部的4GB空间,所以某些页面表项是不可能被访问到的,那该页面表项所占用的空间(32位)白白浪费了。而在分层处理中就不存在类似的问题,如果目录表中的某个目录项为空,则不用设置其对应的包含1024个页面表项的页表,从而省下一部分空间。当然最坏的情况下,假定一个进程用满全部的4G空间,分两个层次会多出一个目录表(1024*4byte)的开销,不过这种概率是极低的。另外,一个页面是4KB,而一个页面表也是4KB,一个页面刚好可以存下了。这样一来,物理页面的起始地址以及页面表的基地址都与4KB对齐,地址的低12位都为0,而指向物理页面起始地址的页面表项以及指向页面表基地址的目录项,只需要有20位用于指针就够了,剩余的12位则可用于控制字段,目录项的结构体如下:


页表项的结构体与此类似,但没有PS字段,但D字段则有效(D字段在目录项中保留不用),表示该页面已经被写过,所以脏了。最低位的P,表示页面表或者相应的页面是否在内存中,如果P为0,则试图存取该页面时,CPU会触发缺页异常“Page Fault”,注意,这里的异常是内核有意为之,目的是进入内核的异常处理程序,将该页从磁盘上交换分区读入到内存中,并设置相应的基地址,并将P位设置成1。相反,当一个页面已经换出到交换分区后,可将P设置成0,表项中其余字段均无意义,所以可被用来临时存储其他信息,比如被换成的页面在磁盘上的位置信息等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值