内存分页问题

什么是内存分页

实在内存分页机制出现之前,已经有了段式内存管理,这个最早在8086 cpu 就支持了,这个时候寻址方式为“段基址:偏移地址”,而且8086具有20根地址线,而它的寄存器才16位,那么怎么才能用16位的寄存器产生20位的地址呢?intel公司的工程师们就决定将段寄存器16位左移4位然后加上偏移地址(段基址*16+偏移地址),这是由硬件支持的。而存放段基址的分为代码段CS、数据段DS、栈段SS等,指令偏移地址由IP指出。分段寻址是一项伟大的创造,在一定程度上解决了以前程序无法重定位,地址必须写死在程序中的问题。但是想象一下这样场景,内存中已经有几个程序在运行了,但是这时又有新的程序申请执行,可内存空间已经不够容纳新的进程,或者说是内存总空间足够容纳这个程序,但是内存被正在运行的程序分割成大小不等的碎片而导致无法加载程序。那么该怎么办呢?既然内存不够那我就增加内存啊,怎么加???当然是把在内存中的程序一些暂时用不到的段交换到硬盘上,腾出空间来,或者干脆等某个进程运行结束后再加载新的进程。而一个段至少也是64kb,这样大的一块空间频繁的从内存和磁盘之间搬来搬去也太慢了吧,IO一般是一个系统的瓶颈。

实模式&&保护模式

在这里给补充一点关于实模式和保护模式的简单知识: 我们之前不是说了嘛,内存是分段管理的,而寻址是段寄存器中的段基址左移4位加上偏移地址得到的。像这样直接给出段基址就可以得到真实内存的地址的模式就叫作实模式。而保护模式是在实模式上建立起来的,它们产生计算物理地址的方式都相同,都是段基址+偏移地址,但是区别就是如何得到段基址,实模式是将基址直接存在段寄存器中,而保护模式是将段基址统一存放在一张表中,这个表就叫作GDT(Global Descriptor Table)全局描述符表,这里每一个表项就是一个存放的相应段基址和一些控制段属性的标志位。那么我们怎么通过段寄存器找到相应的段基址呢?这就要引出GDTR了,GDTR(Global Descriptor Table Regiestor)全局描述符表寄存器,里面存放的是GDT的起始地址,然后段寄存器就相当于相对这个起始地址的偏移量。这就好比是数组,GDTR是数组名,而段寄存器中存放的就是数组下标。另外说明一下,在保护模式下这样产生的地址叫做线性地址,在没有开启分页的情况下,它就是物理地址。

分页是如何解决分段下的问题的

分页实际是建立在分段基础上的,但是这并不是说分页一定以分段为基础,只是先有的分段,后来的分页也就必须在这一前提下进行。
刚才说过了,再没有开启分页模式下的情况下,线性地址就是物理地址,而线性地址是连续的,那么就要求相应的物理地址也要连续才行。但是再开启分页模式后,线性地址就不在可以直接当物理地址使用(物理地址是指可以直接送到地址总线上用于内存寻址的),而是叫做虚拟地址。它是逻辑上连续的地址空间,但是对应物理地址是否连续就要看是怎么映射了,映射就是map即建立起两个事物之间的连续,这个事物就是物理地址和虚拟地址空间。他们之间映射是有一个叫页表的结构实现。这样我们可以让连续的虚拟内存对应任意的物理地址空间只要他们一样大。而它们确实是一样大的,虚拟内存中叫页,物理内存中是页框,一般他们都是4kb。这样解决了前面我们提到的没有分页的情况下的问题:

  1. 内存一旦被分割成碎片就无法载入较大进程
  2. 以段为单位的交换太大费时间

因为分页可以实现连续的虚拟空间映射到不一定连续的物理内存,而以页为单位的交换则能很快速的完成,毕竟一页才4kb。

分页机制如何实现,如何从虚拟地址转换为物理地址?

img
(转载自https://www.jianshu.com/p/68433e97f864)

所有原创文章采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。
本站部分内容收集于互联网,如果有侵权内容、不妥之处,请联系我们删除。敬请谅解!

评论已关闭

有种脾气叫,不放弃。

梦想是注定孤独的旅行,路上少不了质疑和嘲笑,但那又怎样,哪怕遍体鳞伤也要活的漂亮。

不管现在有多么艰辛,我们也要做个生活的舞者。

命运从来不会同情弱者。

不怕万人阻挡在前方,只怕自己先行投降。