致读者: 博主是一名数据科学与大数据专业大二的学生,真正的一个互联网萌新,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样处于困惑的读者。由于水平有限,博客中难免会有一些错误,有纰漏之处恳请各位大佬不吝赐教!之后会写大数据专业的文章哦。尽管当前水平可能不及各位大佬,但我会尽我自己所能,做到最好☺。——天地有正气,杂然赋流形。下则为河岳,上则为日星。
实验目的
熟悉并掌握动态分区分配的各种算法,熟悉并掌握动态分区中分区回收的各种情况,并能够实现分区合并。用高级语言模拟实现动态分区存储管理。
实验内容
分区分配算法至少实现首次适应算法、最佳适应算法和最坏适应算法中的至少一种。熟悉并掌握各种算法的空闲区组织方式。
分区的初始化——可以由用户输入初始分区的大小。(初始化后只有一个空闲分区,起始地址为0,大小是用户输入的大小)
分区的动态分配过程:由用户输入作业号和作业的大小,实现分区过程。
分区的回收:用户输入作业号,实现分区回收,同时,分区的合并要体现出来。(注意:不存在的作业号要给出错误提示!)
分区的显示:任何时刻,可以查看当前内存的情况(起始地址是什么,大小多大的分区时空闲的,或者占用的,能够显示出来)。
实验要求
(1)内存空间不足的情况,要有相应的显示;
(2)作业不能同名,但是删除后可以再用这个名字;
(3)作业空间回收是输入作业名,回收相应的空间,如果这个作业名不存在,也要有相应的提示。
(4)实验完成后要参加实验答辩。
正文
结果展示
{% checkbox checked, 划重点 %}
为了输入和展示的方便,这次在代码的基础上增加了一组模拟数据,这个模拟数据是上课讲的例题。内置三种算法,分别是FF、BF、WF,这三种算法的区别就是排序算法的不同。
初始化内存空间:
这个地方设置了自定义异常处理类,用来输入整数。
然后选择需要执行的算法
这个地方设置了异常处理,只能够输入这三个字符,其它字符视为错误,需要重新输入。
首先,我们调用模拟数据直接生成最终的结果:
作业表状态:
空闲区表状态:
手动制表:
在线绘图:
这个图是使用plt第三方库绘制的图形,采用散点补帧的形式做成类动画效果,当时和自己本来预想的差别好大,自己预想的是能够根据输入动态改变,后来发现难度有点大,于是换成了这种最后结果的方式进行动画效果。
绘制后图片会自动保存到当前目录下的show.png。
注意,图形没有绘制结束不能够点击关闭否则会出现异常,只有当绘制完成之后才能够关闭窗口从而执行下一步。
手动输入:考虑输入重复作业名,考虑作业无法分配内存,考虑删除作业不存在或已经删除的情况。
重复输入:
无法分配内存
删除情况
在任意的时刻都可以查看信息:
手动打表:
图形展示:
实验总结
这个实验我觉的,可以分为几个步骤,第一就是插入作业的时候,判断是否有重复的作业名,基本的思路大致有这几个:1、使用集合,判断这个作业名已经在集合了。2、直接查找,看看能否找到。对于这些方法,使用python都是比较方便的,在这里我使用的方法是 列表生成式 ,然后可以快速判断作业名已经重复。同样的释作业的时候,也需要查看,作业是否运行。插入完作业肯定要更新数据了。
数据更新:主要分为两个方面,第一个就是作业信息的修改,包括起始地址和结束地址,第二个就是空闲分区是否被利用,如果成功分配并被利用,那么肯定要更新空闲区表,更新空闲区表的起始地址和结束地址,如果这个分区的大小位0,那么就移除这个分区。
释放作业关于分区的释放:分区释放存在两方面的问题,同样是作业信息的修改和空闲分区的修改。作业信息的修改,其实就是,从内存里移除,然后修改作业的状态和作业的起始地址与结束地址。对于空闲区表的修改就有点复杂了,主要分为三种情况:1、释放后与前面的空闲分区合并;2、释放后与后面的空闲分区合并;3、释放后与前面后面的空闲分区合并。不过概括起来就是两个,前面的判断就是空闲分区的结束地址是否和当前作业的起始地址一样,后面的判断就是空闲分区的起始地址是否和当前作业的结束地址一样。
排序函数就是分别处理空闲分区的三种情况。FF首次适应算法,所以分区的排序方式应该是按照起始地址排序。BF最佳适应算法,按照空闲分区从小到大的顺序进行排序。WF与最佳适应算法的排序方法刚好相反。
实验代码
# -*- coding: utf-8 -*-
# @Author: wfy
# @Date: 2020-05-03 11:07:17
# @Last Modified by: wfy
# @Last Modified time: 2020-05-04 09:09:20
import matplotlib.pyplot as plt
import numpy as np
class Solution(object):
"""docstring for Solution"""
def __init__(self, name, size):
super(Solution, self).__init__()
self.name = name
self.size = size
self.start = None
self.end = None
class Memory(object):
"""docstring for Memory"""
def __init__(self, size, method):
super(Memory, self).__init__()
self.size = size
self.had_free = []
self.works = []
self.free = [{'start': 0, 'end': size, 'size': size}]
self.method = method
self.speed = 0.5
def find_work(self, work):
names = [i.name for i in self.works]
return True if work.name in names else False
def get_work(self, work):
if self.find_work(work):
return exec("print('error 作业已存在')")
work = self.update(work)
if work is not None:
self.works.append(work)
def free_work(self, work):
if not self.find_work(work):
return exec("print('error 没有该作业')")
for i in range(len(self.works)):
if self.works[i].name == work.name:
work = self.works[i]
self.works.pop(i)
break
self.update_space(work)
def update_space(self, work):
'''合并空闲空间'''
self.had_free.append(work)
# 需要合并
i = 0
while self.free and i < len(self.free):
# 前面有空间
if self.free[i]['end'] == work.start:
work.start = self.free[i]['start']
self.free.pop(i)
i = 0
i += 1
i = 0
while self.free and i < len(self.free):
# 后面有空间
if work.end == self.free[i]['start']:
work.end = self.free[i]['end']
self.free.pop(i)
i += 1
self.free.append({'start': work.start, 'end': work.end,
'size': work.end - work.start})
self.free.sort(key=self.sort_methods())
def sort_methods(self):
if self.method.lower() in ['ff']:
return lambda x: x['start']
if self.method.lower() in ['bf']:
return lambda x: x['size']
return lambda x: (-x['size'])
def put(self):
space = []
print("-"*11 + "作业表" + "-" * 11)
print("名称 大小 起始地址 结束地址")
for i in range(len(self.works)):
space.append(
{'start': self.works[i].start, 'end': self.works[i].end, 'size': self.works[i].size, 'free': False})
print("{:<6}{:<6}{:<10}{:<10}".format(
self.works[i].name, self.works[i].size, self.works[i].start, self.works[i].end))
print("-"*11 + "空闲区表" + "-" * 11)
print("序号 大小 起始地址 结束地址")
for i in range(len(self.free)):
space.append({'start': self.free[i]['start'], 'end': self.free[i]
['end'], 'size': self.free[i]['size'], 'free': True})
print("{:<6}{:<6}{:<10}{:<10}".format(
i, self.free[i]['size'], self.free[i]['start'], self.free[i]['end']))
print('*' * 30)
space.sort(key=lambda x: x['start'])
for tmp in space:
print("-"*20 + "——————>" + str(tmp['start']))
if tmp['free']:
print('| |')
print('| ' + 'free' + ' |——————>空闲区')
print('| |')
else:
print('|···················|')
print('|·······' + 'busy' + '········|——————>作业使用')
print('|···················|')
print("-"*20 + "——————>" + str(self.size))
def update(self, work):
'''新增作业'''
for i in range(len(self.free)):
if work.size <= self.free[i]['size']:
# 更新空闲区表
self.free[i]['size'] -= work.size
work.start = self.free[i]['start']
work.end = work.start + work.size
self.free[i]['start'] = work.end
if self.free[i]['size'] == 0:
self.free.pop(i)
return work
else:
print("没有足够的空闲空间")
return None
def get_y_ticks(self):
pass
def init_image(self):
fig = plt.figure('lab_three', figsize=(4.5, 7))
plt.title('the lab of memory')
plt.xticks([])
plt.yticks([])
def ani_fun(self, x1, x2, y1, y2):
'''补帧'''
x = np.linspace(x1, x2, 30)
y = np.linspace(y1, y2, 30)
for i in range(29):
plt.plot([x[i], x[i + 1]], [y[i], y[i + 1]], color='k')
plt.pause(0.005)
def drow_image(self):
plt.plot([120, 120], [0, 0])
for work in self.works:
# right down left top
x = [0, 100, 100, 0, 0]
y = [work.start, work.start, work.end, work.end, work.start]
self.ani_fun(0, 100, work.start, work.start)
self.ani_fun(100, 100, work.start, work.end)
self.ani_fun(100, 0, work.end, work.end)
self.ani_fun(0, 0, work.end, work.start)
plt.fill(x, y, color='g', alpha=0.2)
plt.text(50, (work.start + work.end) / 2, r'$work \ name:%s$' %
str(work.name), ha='center')
plt.pause(self.speed)
plt.annotate(r'$%d$' % work.start, xy=(100, work.start), xycoords='data', xytext=(+30, -30),
textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=.2"))
plt.pause(self.speed)
plt.annotate(r'$%d$' % work.end, xy=(100, work.end), xycoords='data', xytext=(
30, -30), textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=.2"))
plt.pause(self.speed)
for space in self.free:
# right down left top
self.ani_fun(0, 100, space['start'], space['start'])
self.ani_fun(100, 100, space['start'], space['end'])
self.ani_fun(100, 0, space['end'], space['end'])
self.ani_fun(0, 0, space['end'], space['start'])
def set_ax(self):
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['left'].set_color('none')
ax.xaxis.set_ticks_position('top')
ax.invert_yaxis()
def show_image(self):
self.init_image()
self.set_ax()
self.drow_image()
plt.savefig('show.png', dpi=300)
plt.show()
class CustomError(Exception):
def __init__(self, ErrorInfo):
super().__init__(self) # 初始化父类
self.errorinfo = ErrorInfo
def __str__(self):
return self.errorinfo
if __name__ == '__main__':
while True:
try:
size = int(input('请输入合法内存整数大小\n'))
method = input('请输入需要执行的算法:FF、BF、WF.不区分大小写\n')
if method.lower() not in ['ff', 'bf', 'wf']:
raise CustomError("唔,输入的方法不正确哦。")
memory = Memory(size, method)
except Exception as e:
print("执行错误:", e)
else:
print("内存生成成功")
break
if input('是否需要使用模拟数据:y/n\n') in ['y']:
memory.get_work(Solution(0, 300))
memory.get_work(Solution(1, 100))
memory.free_work(Solution(0, 300))
memory.get_work(Solution(2, 150))
memory.get_work(Solution(3, 30))
memory.get_work(Solution(4, 40))
memory.get_work(Solution(5, 60))
memory.free_work(Solution(3, 30))
memory.put()
memory.show_image()
exit()
while True:
print('1:申请内存\t\n2:释放内存\t\n3:手动打表\t\n4:图形展示\t\n5:退出\n')
flag = input('请输入执行的编号')
if flag == '1':
name = input('请输入作业名字\n')
size = int(input('请输入作业整数大小'))
memory.get_work(Solution(name, size))
elif flag == '2':
name = input('请输入释放的作业名')
memory.free_work(Solution(name, 0))
elif flag == '3':
memory.put()
elif flag == '4':
memory.show_image()
elif flag == '5':
break
else:
print('输入的内容不合法,请重新输入')
continue