可变分区存储管理:
1、可变分区:
为了解决固定分区因作业装入前,分区的数量和大小确定而造成的内部碎片问题,所以引入了可变分区存储管理。目的就是根据作业对存储空间实际的需求量来划分存储分区。也就是每一个分区与进入该分区的作业大小相同,这样能够有效的解决固定分区引起的内部碎片问题。 这是比较实用的存储管理方法,因为在系统运行时,无法确定分区的的数目与大小,所以这种可变式分区也称动态分区。2、问题引入:
虽然可变分区能够解决内部碎片,但是却引入了外部碎片的问题。 就是对于已经分配了并回收的空间,造成内存空间上的不连续。因此该如何选择内存空间来进行分配给下一个作业?3、解决措施:
解决措施 | 说明 | 图例 |
空闲分区的组织形式 | 在可变式分区存储管理中,常把空闲区组成空闲分区表或空闲分区链表的形式。 1、空闲分区表 空闲分区表的组织类似固定分区的分区说明表,包含空闲分区的起始地址和大小。 因为可变分区数量不确定,造成空闲分区表的长度不定。所以采用空闲分区表占用一定数量的存储单元存放表,增加了系统的开销。 因此常使用空闲分区的链表组织形式。 2、空闲分区链表 空闲分区链表的组织形式:在每个空闲分区的起始部分开辟一个单元,存放一个链表指针和该分区的大小。 链表指针指向下一个空闲分区。而且系统中用一个固定单元作为空闲分区链表的链表头指针,指向第一块空闲分区的首地址,最后一块空闲分区的链表指针存放链尾标志。 因为空闲分区链表组织时,空闲区的信息存放在空闲区内,因此不会额外增加系统的开销。 | |
内存的分配与回收 | 1、分配: 在可变分区管理中,当一个作业需要X大小的存储空间时,系统从链表表头指针开始检索空闲区,直到找到第一个大于等于X的空闲区。 1.1、如果 All(空) < X,则无法分配; 1.2、如果 空闲区 = X, 则修改链表指针,取消该空闲区,并返回用户该空闲区首地址 1.3、如果 空闲区 > X, 则将空闲区一分为二,一个为X分给用户,另一个作为余下部分仍然留在空闲区链表中,并修改相应链表指针所指向的的地址和空闲区大小。 2、回收: 检查回收区与内存中前后空闲区是否相邻, 2.1、如果相邻,则进行合并,并对相应链表指针进行修改; 2.2、不相邻,则应将空闲区插入到空闲区链表的适当位置。 |
4、分配算法(分区适应算法):
在可变分区管理中,对空闲区链表采用不同的组织形式,就对不同的分配和回收算法。分区适应算法 | 说明 | 图例解释 | 图例 |
首次适应算法(First Fit) | 过程: 把空闲分区按其在存储空间中地址递增的顺序链接在一起。 当用户申请一块内存空间时,从空闲分区链表的表头指针开始查找,选择第一个满足要求的空闲分区。 如果这块满足要求的分区大小不等于作业大小,则将其分成两部分,一部分给作业,另一部分仍留在空闲区链表中。 优点: 分配和回收算法比较简单,查找速度快。由于这个算法总是从低地址开始查找,因此留在高地址部分的大空闲区被划分机会少,所以在大作业到来时容易满足。 | 如右图: 1、当系统分配: (a)中,空闲区就是按首次适应算法组织的,链接顺序依次是空闲分区1、2和3.。 作业五需要36k空闲区,那么将从空闲区链表组织形式中的第一个空闲区进行遍历(空闲区1),起始地址40k,然后检测到空闲区1大小满足作业5的大小要求。 此时就将分区1一分为二,一部分(36k)分配给作业,另一部分则仍留在空闲区链表中。并调整链表头指针指向的起始地址为76k 2、当系统回收分区时: 首先检查当前分区是否有前后相邻的空闲区,有则进行合并,且修改相应链表指针指向地址和分区大小。 例如:作业2完成后,需要释放。此时链表头指针仍然指向40k位置,但是因为分区1、2、3需要合并,所以此时空闲区1的链表指针指向的是空闲区5的起始位置(196kb),并且修改分区的大小为116kb。 如果回收的分区不和其他空闲区相邻,则根据起始地址大小把他插入到链表的相应位置。 | |
最佳适应算法(Best Fit) | 过程: 此种算法将空闲分区链表按分区大小从小到大进行组织。当有作业申请内存时,首先找到满足要求的最接近作业大小的空闲分区。 因为作业所需大小和分区的大小相近,从而避免存储管理系统将较大的分区分成两部分。 缺点: 因为作业大小不可能与空闲分区大小相同,所以在分配时总是会产生极小的空闲分区,一段时间后内存中可能就会出现很多这样的小分区。 因为大小而无法分配给其他作业使用,并且由于小分区的数量极多,降低链表查询空闲分区的速度。这些无法使用的小分区称之为外部碎片。 解决措施: 设置一个参数G,用来判断空闲分区是以一分为二的形式分配给作业,还是全部分配给作业。 在分配作业内存之后,剩余的空闲区大小 < G时,就把整个分区分配给该作业,不再划分,反之则将空闲分区一分为二并分配。 | 例如右图: 根据该算法的组织形式,形成的链表顺序就是 分区2 -> 分区 1 -> 分区3,按照分区的大小进行组织,并且链表头指针指向分区2的起始位置。 当作业5(36kb)需要空闲区时,遍历空闲分区链表,找到了第一个满足作业5大小要求的分区2(38kb)。然后分配给作业5,剩余的2kb空闲区仍留在空闲区链表中。 | |
最差适应算法(Worst Fit) | 过程: 这种算法是把空闲区从大到小递减的顺序组织成空闲区链表。 当有一个作业需要空闲分区,则检查空闲区链表中第一个空闲分区是否满足作业要求的大小。如果不满足则无法分配;若满足,则将该空闲区分配给用户,然后修改和调整空闲区链表的指针和空闲区大小。 优点: 查询简单 缺点: 因为每一次都是从最大空闲区进行分配,那么容易导致当有大作业进入时而无法得到足够大小的分区 | 空闲区链表的组织形式:按照空闲分区从大到小链接;当有作业5(36kb)需要空闲区,则遍历空闲区链表;检索到空闲分区3大小满足作业5。 因此分配空闲区给作业5,并且重新组织空闲区链表。因为最大的空闲区已经是分区1了。 |
作业装入顺序 | 首次适应算法 | 最佳适应算法 | 最差适应算法 |
A、B、C | 作业C无法分配 | 作业C无法分配 | 全部满足 |
B、A、C | 全部满足 | 全部满足 | 作业C无法分配 |
作业装入顺序 | 首次适应算法 | 最佳适应算法 | 最差适应算法 |
A、B、C | 作业C无法分配 | 作业C无法分配 | 全部满足 |
B、A、C | 全部满足 | 全部满足 | 作业C无法分配 |
5、可变分区存储管理的地址重定位:
重定位方式 | 说明 | 图例 |
静态重定位 | 因为用户作业进入内存后,程序的逻辑地址实现了重定位,所以不能在内存中再次进行移动。 经过一段时间的运行,内存中外部碎片越来越多,导致出现一种情况:就是所有碎片大小总和大于或等于作业大小,但是却无法将作业装入内存中。 | |
动态重定位 | 为了解决因为外部碎片导致的问题,所以采用动态重定位技术,使得程序能够在内存中移动。并采用紧凑技术:将小碎片全部集中起来形成一个大分区。(类似JVM的标记整理) 也就是移动用户分区中的程序,使得用户程序都集中在一端,使碎片都集中于另一方,这样就可以保证所有碎片都是连续并且形成连成一个较大的分区。 同时解决内部和外部碎片的问题。 可变式分区的存储保护采用的是:基址-限长存储保护方式.可参考:存储管理的基本功能 |