Python模拟内存存储管理
上一篇 / 下一篇 2014-02-24 00:03:27 / 个人分类:Python
__author__ = 'SHUHUA'
#-*- coding: UTF-8 -*-
import random
fstr =''#分区信息--没必要
jstr=''#作业信息
mem_size=1000 #内存总大小
mem_free_size=0 #内存空闲大小
flist=[]#空闲分区列表,每个元素都是一个列表
jlist=[]#作业列表,每个元素都是一个列表
ID=0
ADDR=1
L_SIZE=2#分区块size
L_Z=3#分区作业
J_SIZE=1#作业size
J_BLOCK=2#作业对应区块
J_STATE=3#作业状态
titlebar_f='分区id 分区addr 分区size 分区作业/情况\n'
titlebar_z='作业id 作业size 对应区块 作业状态\n'
message_change=''#对内存改变情况的提醒信息
def show_men():#打印内存分区
global flist,titlebar_f,message_change
strs=''
for i in range(len(flist)):
strs += str(flist[i][ID]).ljust(15) + str(flist[i][ADDR]).ljust(15) +str(flist[i][L_SIZE]).ljust(15) +str(flist[i][L_Z]).ljust(15)+'\n'
v1.set(titlebar_f+ strs)
v_message.set(message_change)
def show_job():#打印作业
global jlist,titlebar_z
strs=''
for i in range(len(jlist)):
strs += str(jlist[i][ID]).ljust(15) +str(jlist[i][J_SIZE]).ljust(15) +str(jlist[i][J_BLOCK]).ljust(20) +str(jlist[i][J_STATE]).ljust(15)+'\n'
v2.set(titlebar_z+ strs)
def random_free_Fenqu():#随机生成分区
global mem_free_size,mem_size,fstr,flist,titlebar_f
mem_free_size =0#每次都重新分配所有空白内存
fstr=''#每次都刷新内容
i=0 #每次从0开始分区
del flist[:] # 每次都清空列表
start=['始',' -> ',mem_free_size,' #']
while (mem_free_size < 500):#只要 空白分区总量 小于 内存总量 就允许划分空白区 (mem_size - 50)
size = random.randint(5,300)#随机free memory块的大小
addr = random.randint(0,1000)#随机free memory块的首址
length = len(flist) #空白分区list为空时长0
useful = True #随机addr和size是否可用标志
if length > 0:#如果内存中有空白分区块
for m in range(length):#判断是否跟已有空白分区有交集
a=flist[m][ADDR]
s=flist[m][L_SIZE]
if((addr + size)> mem_size):
useful = False
break
elif((a - addr)> 0):#如果 首址 在 当前空白区首址 前面
if(a-addr-size) < 5:#如果 尾址 距 当前空白区首址 小于5个单位
useful = False
break
else:#如果 首址 在 当前空白区首址 后面
if (addr-a-s) < 5:#如果 首址 距 当前空白区尾址 小于5个单位
useful = False
break
if useful:
new_men=[i,addr,size,'未分配']#生成新的空白分区
flist.insert(i,new_men) # 插入空白分区链表
i = i+1
mem_free_size += size#成功分配了一个空白块,空白分区总容量增大
fstr += str(new_men[ID]).ljust(15) + str(new_men[ADDR]).ljust(15) +str(new_men[L_SIZE]).ljust(15) +str(new_men[L_Z]).ljust(15)+'\n'
last=['总','->',mem_free_size,'< 0.8*1000']
st = str(start[ID]).ljust(15) + str(start[ADDR]).ljust(15) +str(start[L_SIZE]).ljust(15) +str(start[L_Z]).ljust(15)+'\n'
fstr += str(last[ID]).ljust(15) + str(last[ADDR]).ljust(15) +str(last[L_SIZE]).ljust(15) +str(last[L_Z]).ljust(15)+'\n'
v1.set(titlebar_f+ st +fstr)
def random_free_job():#随机生成作业15个
global jlist,jstr,titlebar_z
del jlist[:]
jstr=''#每次随机生成作业都清空旧信息
for j in range(15):
jsize = random.randint(5,200)#因为最大空白分区才300
new_job =[j,jsize,'未分配','就绪']
jlist.insert(j,new_job)#插入 作业所需内存分配表
jstr += str(new_job[ID]).ljust(15) +str(new_job[J_SIZE]).ljust(15) +str(new_job[J_BLOCK]).ljust(15) +str(new_job[J_STATE]).ljust(15)+'\n'
v2.set(titlebar_z+ jstr)
import tkMessageBox
def return_mem():#按id回收内存分区
global flist,jlist,message_change #回收后要修改信息
message_change=''#每次回收信息都清空
id = e1.get()#要回收的内存分区id
if id.isdigit():
id = int(id)
if 0 <= id < len(flist):
if (str(flist[id][L_Z])=='未分配') or('割自' in str(flist[id][L_Z])):#如果要回收的分区本来就是空闲的
tkMessageBox.showwarning(title=u"警告", message=str(id)+"号分区尚未使用,无法回收", detail=u"请重新输入要回收的分区id", icon="warning")
else:
#修改为空白区
flist[id][L_Z]='未分配'
c1=False#判断是否有合并上一分区
c2=False#判断是否有合并下一分区
#看要回收的分区的首址是否是其他分区的尾址+1
for i in range(len(flist)):#因为flist每个元素首址是随机的,所以要遍历全部比较
item=flist[i]#当前比较的项
if (item[ADDR] +item[L_SIZE] == flist[id][ADDR]) and item[ID]:#地址相邻
if (str(item[L_Z])=='未分配') or('割自' in str(item[L_Z])):#也是空白
flist[i][L_SIZE] += flist[id][L_SIZE]
flist[id][ADDR]=' --'
flist[id][L_SIZE]=' --'
flist[id][L_Z]=' --'
c1=True
message_c ='小tips: 回收的'+str(id)+'号分区与其前一分区即'+str(item[ID])+'号空白分区合并'
#看要回收的分区的尾址+1是否是其他分区的首址
for i in range(len(flist)):#因为flist每个元素首址是随机的,所以要遍历全部比较
item=flist[i]#当前比较的项
if item[ADDR] == flist[id][ADDR]+flist[id][L_SIZE]:#地址相邻
if (str(item[L_Z])=='未分配') or('割自' in str(item[L_Z])):#也是空白
flist[id][L_SIZE] += flist[i][L_SIZE]
flist[i][ADDR]=' --'
flist[i][L_SIZE]=' --'
flist[i][L_Z]=' --'
c2=True
message_c ='小tips: 回收的'+str(id)+'号分区与其后一分区即'+str(item[ID])+'号空白分区合并'
#回收后,相应作业也要回收
for i in range(len(jlist)):
if jlist[i][J_BLOCK]==id:
jlist[i][J_BLOCK]='ok'
jlist[i][J_STATE]='完成'
break
if c1 and c2:
message_change='小tips: 回收的'+str(id)+'号分区与其前一分区即'+str(item[ID])+'号空白分区及其后一分区即'+str(item[ID])+'号空白分区合并'
else:
message_change=message_c
show_men()
show_job()
else:
tkMessageBox.showwarning(title=u"警告", message="分区id号越界", detail=u"请重新输入要回收的分区id", icon="warning")
else:
tkMessageBox.showwarning(title=u"警告", message="请输入正确的分区id号", detail=u"只允许数字", icon="warning")
def first_fit():#首次适应算法:以地址递增的次序查找满足的空白分区,割给请求者后,余下部分仍留在空白分区。--其实我还可以在页面打印按物理地址顺序的链表哦
global flist,jlist
new_flist = sorted(flist,cmp=lambda x,y:cmp(x[ADDR],y[ADDR]))#按地址对空白分区排列
for jid in range(len(jlist)):#对于每一个作业
if jlist[jid][J_BLOCK]=='未分配' or jlist[jid][J_BLOCK]=='分配 fail':
chenggong = False
kid = 0 #记录flist中合适的分区的ID
for i in range(len(new_flist)):#从链首开始找适合的内存空白分区
if new_flist[i][L_Z] =='未分配'or ('割自' in str(new_flist[i][L_Z])):
lt = new_flist[i][L_SIZE] - jlist[jid][J_SIZE]
if lt >= 0:
chenggong = True#有适合的分区
kid = new_flist[i][ID]
#将适合分区的上部变为jid作业占有
flist[okid][L_Z]=jid
flist[okid][L_SIZE]= jlist[jid][J_SIZE]
#将分区割剩的部分append到flist尾
if lt >0:
last_id = len(flist)
last_addr = flist[okid][ADDR] + jlist[jid][J_SIZE]
last_z = '割自'+str(okid)
last=[last_id,last_addr,lt,last_z]
flist.append(last)
new_flist = sorted(flist,cmp=lambda x,y:cmp(x[ADDR],y[ADDR]))#也更新new_flist
break
if chenggong:
jlist[jid][J_STATE]=str(1)
jlist[jid][J_BLOCK]=okid
else:
jlist[jid][J_BLOCK]='分配 fail'
#打印分配结果
show_job()
show_men()
def next_fit():#循环首次适应算法:从上次找到的空闲分区的下一个空闲分区开始查找。
global flist,jlist
new_flist = sorted(flist,cmp=lambda x,y:cmp(x[ADDR],y[ADDR]))#按地址对空白分区排列
zhizhen=0 #记录为每个作业查找空闲块时的起始地址
for jid in range(len(jlist)):#对于每一个作业
if jlist[jid][J_BLOCK]=='未分配' or jlist[jid][J_BLOCK]=='分配 fail':
chenggong = False
kid = 0 #记录flist中合适的分区的ID
for i in range(zhizhen,len(new_flist)):#每次都上次找到的空闲分区的下一个空闲分区开始查找适合的内存空白分区
if new_flist[i][L_Z] =='未分配'or ('割自' in str(new_flist[i][L_Z])):
lt = new_flist[i][L_SIZE] - jlist[jid][J_SIZE]
if lt >= 0:
chenggong = True#有适合的分区
if i < (len(new_flist)-1):
zhizhen = i+1
kid = new_flist[i][ID]
#将适合分区的上部变为jid作业占有
flist[okid][L_Z]=jid
flist[okid][L_SIZE]= jlist[jid][J_SIZE]
#将分区割剩的部分append到flist尾
if lt >0:
last_id = len(flist)
last_addr = flist[okid][ADDR] + jlist[jid][J_SIZE]
last_z = '割自'+str(okid)
last=[last_id,last_addr,lt,last_z]
flist.append(last)
new_flist = sorted(flist,cmp=lambda x,y:cmp(x[ADDR],y[ADDR])) #也更新new_flist
break
if chenggong:
jlist[jid][J_STATE]=str(1)
jlist[jid][J_BLOCK]=okid
else:
jlist[jid][J_BLOCK]='分配 fail'
#打印分配结果
show_job()
show_men()
def best_fit():
global flist,jlist
for jid in range(len(jlist)):#对于每一个作业
new_flist = sorted(flist,cmp=lambda x,y:cmp(x[L_SIZE],y[L_SIZE]))#每次找适合的分区都要按大小对空白分区排列后再找
if jlist[jid][J_BLOCK]=='未分配' or jlist[jid][J_BLOCK]=='分配 fail':
chenggong = False
kid = 0 #记录flist中合适的分区的ID
for i in range(len(new_flist)):#从链首开始找适合的内存空白分区
if new_flist[i][L_Z] =='未分配'or ('割自' in str(new_flist[i][L_Z])):
lt = new_flist[i][L_SIZE] - jlist[jid][J_SIZE]
if lt >= 0:
chenggong = True#有适合的分区
kid = new_flist[i][ID]
#将适合分区的上部变为jid作业占有
flist[okid][L_Z]=jid
flist[okid][L_SIZE]= jlist[jid][J_SIZE]
#将分区割剩的部分append到flist尾
if lt >0:
last_id = len(flist)
last_addr = flist[okid][ADDR] + jlist[jid][J_SIZE]
last_z = '割自'+str(okid)
last=[last_id,last_addr,lt,last_z]
flist.append(last)
break
if chenggong:
jlist[jid][J_STATE]=str(1)
jlist[jid][J_BLOCK]=okid
else:
jlist[jid][J_BLOCK]='分配 fail'
#打印分配结果
show_job()
show_men()
def algorithm():#采用何种算法
global message_change
message_change=''#每次开始分配都清空tips信息
if r.get() == '1':
first_fit()
elif r.get() == '2':
next_fit()
else :
best_fit()
#Tk提供了三个管理器来帮助我们:Pack Grid Place-----------------------------main-------------------------
from Tkinter import *
top = Tk() #根窗口
top.title=('内存管理')
top.resizable(False, False)
top.geometry('610x600')
c1=Label(top,text='操作')
c2=Label(top,text='选择算法')
m1=Label(top,text='某时刻内存空闲链列表')
m2=Label(top,text='作业所需内存分配表')
c3=Label(top,text='分区id:')
c1.place(x=0,y=0)
c2.place(x=310,y=0)
m1.place(x=5,y=220)
m2.place(x=310,y=220)
b1=Button(top,text = "随机生成空闲分区",bg = "SkyBlue",width=15,command = random_free_Fenqu)
b2=Button(top,text = "随机生成作业",bg = "SkyBlue",width=15,command = random_free_job)
b3=Button(top,text = "开始分配",bg = "LightSalmon",width=15,command = algorithm)
b4=Button(text = "回收", command = return_mem)
v_message = StringVar()
Message(top,width = 400,textvariable = v_message).place(x=0,y=200)
e1 = Entry(width=3)
b1.place(x=5,y=30)
b2.place(x=5,y=80)
b3.place(x=5,y=130)
c3.place(x=5,y=170)
e1.place(x=50,y=170)
b4.place(x=85,y=170)
auth=Label(top,text='存储管理实验\n 11级计科3班\n3211005813\n 青春痘\n 2013年12月25日',bg="LightGrey")
auth.place(x=500,y=0)
r = StringVar() #使用StringVar生成字符串变量用于单选框组件
r.set('1') #初始化变量值
radio = Radiobutton(top, #生成单选框组件
variable = r, #设置单选框关联的变量
value = '1', #设置选中单选框时其所关联的变量的值
indicatoron = 0,
bg = "SkyBlue",
text = '首次适应算法'.center(25)) #设置单选框显示的文本
radio.place(x=310,y=50)
radio = Radiobutton(top,
variable = r,
value = '2', #当选中单选框时,r的值为2
indicatoron = 0,
bg = "SkyBlue",
text = '循环首次适应算法'.center(25))
radio.place(x=310,y=100)
radio = Radiobutton(top,
variable = r,
value = '3',
indicatoron = 0,
bg = "SkyBlue",
text = '最佳适应算法'.center(25))
radio.place(x=310,y=150)
v1 = StringVar()
v1.set(titlebar_f)
Message(top,width = 400,textvariable = v1,bg = "Tan" ).place(x=5,y=250)
v2 = StringVar()
v2.set(titlebar_z)
Message(top,width = 400,textvariable = v2,bg = "Tan").place(x=311,y=250)
mainloop()
TAG: