终于也是跨过了处理机管理,来到内存管理的内容了。目前基本存储管理这一章还差分页、分段以及段页三种管理方式没有学,之所以在学之前来写这一篇文章,主要是觉得这一章的内容过于零碎了,不易成逻辑又很容易忘掉,所以写这一篇来串一下已学的内容,在复习的基础上为学接下来的做一些铺垫。
在第一节基本就把存储管理的大致框架说明了,首先是一些基本概念,之后是存储管理的基本功能。基本功能几乎是整个第六章的内容,内存的分配与回收功能是最主要的,已经学的分区以及后面的分页,分段等等都是说这个的。接着是地址重定位,这在第一节已经说清楚了,之后是内存的共享和保护,这里课本上涉及不多,但是在看课时也略微学到一些。最后是内存的扩充,这一章主要介绍了覆盖和交换技术,至于虚拟内存技术要留在下一章讲了。
那么,大概了解框架后,我们就正式开始。
举个例子:一段程序在内存中的存放位置是100-149,这是它的物理地址。那么程序员在编写时,可以将逻辑地址设为0-50。
那么问题就来了,我们写的时候直接用物理地址写,然后再装入内存不就好了,为什么要再使用一个逻辑地址?原因是在多道程序环境中,程序员无法知道程序被装入内存的哪个区域执行。在单道程序环境下,是可以使用物理地址的。
这里用一张图说明一个程序从编写到装入内存需要经历的事,我们假设编辑的是一个C程序:
在这个过程中我们需要研究的重点是:
我们知道逻辑地址是一个相对地址,和其加载到内存中的物理地址是不对应的,所以程序想顺利执行就得把逻辑地址转换成物理地址,这个过程就称之为地址重定位。
我们根据地址重定位的时机不同,分为静态地址重定位与动态地址重定位。
重定位时机:程序被装入内存的过程中,程序运行前
物理地址 = 装入内存的起始地址 + 逻辑地址
图解:
优点:不需要硬件支持(动态需要重定位寄存器)
缺点:
😶🌫️分割线———-
重定位时机:程序运行过程中。即程序在装入内存中先不地址转换,等到执行时,再转换。(也就是装入的是逻辑地址)
使用重定位寄存器存放装入模块存放的起始位置
物理地址 = 重定位寄存器的值 + 逻辑地址
优点
缺点:需要硬件支持。
现代OS基本采用的是动态地址重定位。
根据地址重定位的方式不同,其装入内存的方式也不同,我们分为3类,其和地址重定位的方式是一一对应的。
装入模块使用物理地址直接装进去,无需地址重定位。
这是在单道程序设计阶段实现的,用户提前知道物理地址,因此无需转换。
即使用静态地址重定位的装入方法,不再赘述。
即使用动态地址重定位的装入方式,装入内存的是逻辑地址,直到运行时利用重定位寄存器转换为物理地址。
看完最核心的两步之后,我们折返回来看看链接。链接的目的形成完整的逻辑地址,我们根据链接的时机,也可以分为三种链接方式:
在上面的地址重定位是内存管理的基本功能之一,现在我们再来讲讲内存管理的另一个基本功能——内存的分配和回收。
其按照分配的方式可分为连续分配存储管理和非连续分配存储管理。
在正式开始之前,我们先明确两个概念——内碎片和外碎片
在如下的讲解中我们都会分析这种方式是否有内碎片或外碎片。下面就来正式看一下这节要说的三种连续分配方式:
内存被分为系统区和用户区。
单一连续分配即一个进程占一个用户区,显然这种情况只使用于单道程序环境下。
有内碎片:很显然啦,那么大一个用户区就一个进程,存储器利用很低
无外碎片:大概是因为全是内碎片?
可能是大佬们觉得单一分配太低效辣,然后多道程序环境一出,就想着一片内存给多个进程,咋办呢?于是就把用户区分区了,每个分区装一个程序,分区一旦划好,不能重分。而且分区大小和数量都是固定的,这也就是叫固定分区的原因了。
划分方式:根据划定的分区大小是否相等,分为分区大小相等&分区大小不等。
看图
这种方式就有点缺乏灵活性,比如来一个12MB的大程序,就没有它的容身之地,来一些很小的程序,一个程序占一个分区,就会产生大量内碎片。
但不会产生外碎片,为什么?因为是固定分区,一个分区就一个进程,外碎片大概是要动态分区才会产生。
虽然这种方式很呆,但不可否认的是,其适用于一台计算机控制多个相同对象的场合。
看图
就一定程序上解决了分区大小相等的问题,系统可以根据程序的大小选择适合的分区,减少了内碎片的数量(但是也有)。而且较大的分区也有机会找到一个大分区运行。
既然一个用户区被划了好几块,就得用一个数据结构管管它——分区说明表。
功能是来记录每个分区的大小,起始地址和状态等信息。
优点
缺点
分区不是固定划分好的,而是根据进程实际需要动态划分(可以让分区大小正好适合进程需要),果然是大佬们看不下去静态分区有那么多内碎片了。
分配
回收:进程运行完时内存需回收分区,我们需要考虑回收分区是否与空闲分区相邻
总体来看:(这一点是我想写的一点)
我们最先设计了首次适应算法,这种算法的缺陷是每次都要从头查找,都需要检索一遍低地址的小分区。我们为了解决这个问题设计了循环首次适应算法,从上次分配的空闲分区的下一个分区开始查找。即循环首次适应不会查找已分配分区之前的分区。那如果来了一个更小的分区,这个分区恰好在之前的小分组可以满足,此时我们希望直接用上面的小分区,这时我们希望算法是首次适应算法。实际上,首次适应算法也隐含了一点最佳适应算法的优点。
而此时我们如果继续使用循环首次适应的算法,那么这个小分区就会占用下面的分区,可能会导致高地址部分的大分区被使用,导致如果来了一个大分组,导致其没有大分区可用,所以,循环首次适应算法也隐含了一点最大适应算法的缺点。
四种算法中,首次适应算法的效果反而更好。