一、实验目的:
目的:熟悉并掌握动态分区分配的各种算法,熟悉并掌握动态分区中分区回收的各种情况,并能够实现分区合并。
任务:用高级语言模拟实现动态分区存储管理。
二、实验内容:
1、实验内容
分区分配算法至少实现首次适应算法、最佳适应算法和最坏适应算法中的至少一种。熟悉并掌握各种算法的空闲区组织方式。
分区的初始化——可以由用户输入初始分区的大小。(初始化后只有一个空闲分区,起始地址为0,大小是用户输入的大小)
分区的动态分配过程:由用户输入作业号和作业的大小,实现分区过程。
分区的回收:用户输入作业号,实现分区回收,同时,分区的合并要体现出来。(注意:不存在的作业号要给出错误提示!)
分区的显示:任何时刻,可以查看当前内存的情况(起始地址是什么,大小多大的分区时空闲的,或者占用的,能够显示出来)。
2、实验要求
(1)内存空间不足的情况,要有相应的显示;
(2)作业不能同名,但是删除后可以再用这个名字;
(3)作业空间回收是输入作业名,回收相应的空间,如果这个作业名不存在,也要有相应的提示;
(4)实现FF、BF、WF内存分配算法种的至少两种。
(5)实验完成后要参加实验答辩。
三、实验代码
import copy
class Memory(object):
def __init__(self, start, end, length, state=1, name=0):
self.start = start
self.end = end
self.length = length
self.state = state # state为1表示内存未分配
self.name = name ##name为0是未分配,其余为作业名称
class CustomError(Exception):
def __init__(self, ErrorInfo):
super().__init__(self)
self.errorinfo = ErrorInfo
def __str__(self):
return self.errorinfo
def showMemory(list):
print("分配状态\t分区名称\t起始地址\t终止地址\t分区大小")
for i in range(0, len(list)):
p = list[i]
if p.state == 1:
print('空闲\t', " ", p.name, " ", p.start, " ", p.end, " ", p.length)
else:
print('已分配\t', "", p.name, " ", p.start, " ", p.end, " ", p.length)
print("")
# 首次适应算法
def FF(work_name, work_length, list):
for i in list:
if i.name == work_name:
print('作业已存在')
return
for i in range(0, len(list)):
p = list[i]
if p.state == 1 and p.length > work_length: # p是当前未分配内存的大小
a = Memory(p.start, p.start + work_length - 1, work_length, state=0, name=work_name) # a是当前为作业分配的分区
node2 = Memory(p.start + work_length, p.end, p.length - work_length, 1, 0) # 空闲分区
del list[i] # 删除当前的分区
list.insert(i, node2) # 插入空闲分区
list.insert(i, a) # 插入已分配当前作业的分区
showMemory(list)
return
if p.state == 1 and p.length == work_length:
del list[i] # 删除当前的分区
a = Memory(p.start, p.start + work_length - 1, work_length, state=0, name=work_name)
list.insert(i, a)
showMemory(list)
return
print("内存空间不足")
def freeMemory(work_name, li):
names = []
for i in range(0, len(li)):
names.append(li[i].name)
if work_name not in names:
print("作业%s不存在..." % work_name)
return
for i in range(0, len(li)):
p = li[i]
if p.name == work_name:
p.state = 1 # 状态设为未分配
target = i # 记录该分区的位置
p.name = 0 # 名称设置为初始0
break
# 向前合并空闲块
if target - 1 >= 0:
if li[target - 1].state == 1: # 如果前一个分区是未分配状态
a = Memory(li[target - 1].start, li[target].end, li[target - 1].length + li[target].length, 1, 0)
del li[target - 1] # 删除前一个分区
del li[target - 1] # 删除当前的分区
li.insert(target - 1, a)
target = target - 1 # 此步非常关键,将target指针指向已合并的分区,如果该分区后还有空闲分区,则可直接处理
# 向后合并空闲块
if target + 1 < len(li):
if li[target + 1].state == 1: # 如果后一个分区是未分配状态
a = Memory(li[target].start, li[target + 1].end, li[target].length + li[target + 1].length, 1, 0)
del li[target]
del li[target]
li.insert(target, a)
showMemory(li)
##最佳适应算法
def select_sort(list):
# 按分区的大小从小到大排序
count = len(list)
for i in range(0, count):
for j in range(i + 1, count):
if list[i].length <= list[j].length:
list[i], list[j] = list[j], list[i]
return list
def select_sort2(list):
# 按分区的大小从大到小排序
count = len(list)
for i in range(0, count):
for j in range(i + 1, count):
if list[i].length >= list[j].length:
list[i], list[j] = list[j], list[i]
return list
def BF(work_name, work_length, li):
for i in li:
if i.name == work_name:
print('作业已存在')
return
q = copy.copy(li)
q = select_sort(q) # 从小到大排序,给所有已分配和未分配的分区排序
s = -1
s2 = -1
for i in range(0, len(q)):
p = q[i]
if p.state == 1 and p.length > work_length: # 分区若为未分配
s = p.start # s得到起始位置
elif p.state == 1 and p.length == work_length:
s2 = p.start
if s == -1 and s2 == -1:
print("内存空间不足")
return
for i in range(0, len(li)):
p = li[i]
if p.start == s:
a = Memory(p.start, p.start + work_length - 1, work_length, state=0, name=work_name) # 修改后的分区
node2 = Memory(p.start + work_length, p.end, p.length - work_length, 1, 0) # 空闲分区
del li[i]
li.insert(i, node2)
li.insert(i, a)
showMemory(li)
return
elif p.start == s2:
p.state = 0
p.name = work_name
showMemory(li)
return
def WF(work_name, work_length, li):
for i in li:
if i.name == work_name:
print('作业已存在')
return
q = copy.copy(li)
q = select_sort2(q) # 从大到小排序,给所有已分配和未分配的分区排序
s = -1
s2 = -1
for i in range(0, len(q)):
p = q[i]
if p.state == 1 and p.length > work_length: # 分区若为未分配
s = p.start # s得到起始位置
elif p.state == 1 and p.length == work_length:
s2 = p.start
if s == -1 and s2 == -1:
print("内存空间不足")
return
for i in range(0, len(li)):
p = li[i]
if p.start == s:
a = Memory(p.start, p.start + work_length - 1, work_length, state=0, name=work_name) # 修改后的分区
node2 = Memory(p.start + work_length, p.end, p.length - work_length, 1, 0) # 空闲分区
del li[i]
li.insert(i, node2)
li.insert(i, a)
showMemory(li)
return
elif p.start == s2:
p.state = 0
p.name = work_name
showMemory(li)
return
if __name__ == '__main__':
while True:
try:
print("请输入合法内存大小:")
size = int(input())
a = Memory(0, size - 1, size, state=1, name=0)
memorySpace = []
memorySpace.append(a)
print("1.首次适应算法(FF)")
print("2.最佳适应算法(BF)")
print("3.最佳适应算法(WF)")
choice = int(input("请输入分配执行的算法:\n"))
if choice not in [1, 2, 3]:
raise CustomError("输入错误,请重新输入")
except Exception as e:
print(e)
else:
print("大小为%d的内存空间已完成初始化..." % size)
# showMemory(memorySpace)
print("")
break
# while True:
# print('1:初始化\t\n2:分配空间\t\n3:回收\t\n4:显示\t\n5:退出\n')
while (True):
print('1:初始化\t\n2:分配\t\n3:回收\t\n4:显示\t\n5:退出')
select = input('请输入想要执行的功能:')
if select == '5':
break
elif select == '1':
print("请输入合法内存大小:")
size = int(input())
a = Memory(0, size - 1, size, state=1, name=0)
memorySpace = []
memorySpace.append(a)
elif select == '2':
repeat = 'y'
while (repeat == 'y'):
if choice == 1: # FF算法
try:
workSize = input('请输入作业名称和大小:').split()
FF(workSize[0], int(workSize[1]), memorySpace)
except Exception as e:
print("输入有误,请重新输入")
else:
repeat = input('是否继续(y/n):')
elif choice == 2: # BF算法
try:
workSize = input('请输入作业名称和大小:').split()
BF(workSize[0], int(workSize[1]), memorySpace)
except Exception as e:
print("输入有误,请重新输入")
else:
repeat = input('是否继续(y/n):')
elif choice == 3: # WF算法
try:
workSize = input('请输入作业名称和大小:').split()
WF(workSize[0], int(workSize[1]), memorySpace)
except Exception as e:
print("输入有误,请重新输入")
else:
repeat = input('是否继续(y/n):')
elif select == '3':
showMemory(memorySpace)
workName = input('请输入所要删除作业的名称:')
freeMemory(workName, memorySpace)
else:
showMemory(memorySpace)
四、实验结果
1.首先输入合法内存大小:50,并选择最坏适应算法WF:
2.选择2,依次进行三个作业的内存分配:
3.1)对于数据1,60,作业大小超过分区的总大小,因此提示“内存空间不足”;
3.2)对于数据1,10,存在大于等于该作业大小的分区0,因此分配至分区0;
3.3)对于数据1,20,因为分区中已经存在同名作业,因此提示“作业已存在”;
3.4)对于数据2,20,存在大于等于该作业大小的分区0,因此分配至分区0;
4.选择3进行内存的回收,回收作业1:
作业1所在分区状态变为“空闲”,名称变为默认值。
6.回收作业2:
回收区2前后有空闲区,一块进行合并回收形成一个空闲分区。
7.分配大小为10的作业1:
8.分配大小为10的作业2:
9.分配大小为9的作业3:
10.回收作业1:
11.分配大小为11的作业4:
只有大小为21的分区满足作业4,因此分配至最后一个分区。
12.分配大小为5的作业1:
第一个分区和最后一个分区的大小都为10,内存大小的情况下,地址靠前的分区优先分配,因此将作业1分配至第一个分区。
13.回收作业2:
回收区2前面有一个空闲分区,将其合并为一个空闲分区。
14.回收作业4:
回收区3后面有一个空闲分区,将其合并为一个空闲分区。
15.回收作业1:
回收区1后面有一个空闲分区,将其合并为一个空闲分区。
16.回收作业3:
回收区3前后各有一个空闲分区,将其合并为一个空闲分区。
FF首次适应算法和BF最佳适应算法测试方法与之类似,结果符合预期。
五、实验总结
通过本次动态分区存储管理实验,我熟悉并掌握了动态分区分配的三种算法:FF首次适应算法、BF最佳适应算法和WF最坏适应算法及其相应的分区组织方式。此外我掌握了不同情况下的分区回收,包括回收区前有空闲区,回收区后有空闲区,回收区前后有空闲区;
在具体的代码实现中,我采用的是Python语言,因为Python中列表这一数据结构可以较为简便地实现分区的增删改,在处理BF和WF内存分配算法时需要注意在分区空间相同时优先向低地址的分区分配作业,这个要求的实现如果不细想的话可能觉得比较复杂,实际在仔细考虑之后只需将排序算法中小于或大于的比较中加上等号就可实现了,因为本身分区是按地址从小到大依次排序的,那么在加上等号之后就可实现在新的排序中即使分区的大小相同,也是地址较小的靠前。
同时在合并空闲分区的这一过程中,有一个十分关键的操作:target = target - 1,在合并完回收区的前一个空闲分区后可以使target指针重新指向已合并后的分区,如果该分区后还有空闲分区则可直接利用对后面空闲分区处理的函数,使得代码更加地简洁。
其次对于实验要求中的三个要求,对于内存空间不足的情况需要给出内存不足的提示的实现,可以通过遍历内存空间中的空闲分区将其空间与作业的空间进行比较,若所有分区的大小都小于作业的大小,则给出“内存空间不足”的它提示;对于分配时作业不能同名的这一要求,实现较为简单,通过遍历分区名称并与作业的名称进行比较,如果相同则直接return返回;对于作业空间回收时若作业名不存在的提示,实现与上述做法类似。
总之这次实验大大地加深了我对动态分区存储管理的理解,其次也进一步锻炼了自身的coding能力,是一次收获不小的实验。