Python实现页面置换算法
FIFO LRU OPT
页面置换——FIFO、LRU、OPT
页面置换算法:
在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。
一、FIFO(先进先出置换算法)
1.算法解析
算法原理:当需要淘汰一个页面时,总是选择驻留主存时间最长的页面进行淘汰,即先进入主存的页面先淘汰。其理由是:最早调入主存的页面不再被使用的可能性最大。
如图所示(示例):
2.代码实现
//旧版
def FIFO(page,arr):
print("FIFO页面置换过程为:" )
result=[]
loss_page=0
sum=0
for item in arr:
if len(result)==page:
for j in range(sum, len(arr)):
if arr[j] in result:
print("no exchange")
print("第%i页"%j,end="")
print(result)
else:
del result[0]
result.append(arr[j])
loss_page += 1
print("第%i页" % j,end="")
print(result)
break
elif item in result:
print("no exchange")
print("第%i页" % sum,end="")
print(result)
sum+=1
else:
result.append(item)
loss_page+=1
print("第%i页" % sum,end="")
print(result)
sum+=1
result_page=float((loss_page)/len(arr))
print("FIFO缺页率为:%.2f"%result_page)
//新版本 2024年10月16日
def FIFO(page_capacity, page_references):
print("FIFO页面置换过程为:")
memory = [] # 用于存储当前在内存中的页面
page_faults = 0 # 记录缺页次数
for i, page in enumerate(page_references):
if page not in memory:
# 如果页面不在内存中,发生缺页
page_faults += 1
if len(memory) >= page_capacity:
# 如果内存已满,移除最早进入的页面
memory.pop(0)
# 添加新页面到内存
memory.append(page)
# 打印当前页面引用和内存状态
print(f"第{i+1}页: 内存状态 {memory}")
# 计算缺页率
page_fault_rate = page_faults / len(page_references)
print(f"FIFO缺页率为:{page_fault_rate:.2f}")
# 示例使用
page_capacity = 3 # 内存页框数
page_references = [7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2] # 页面引用序列
FIFO(page_capacity, page_references)
二、LRU(最近最近未使用算法)
1.算法解析
算法原理利用局部性原理,根据一个作业在执行过程中过去的页面访问历史来推测未来的行为。它认为过去一段时间里不曾被访问过的页面,在最近的将来可能也不会再被访问。所以,这种算法的实质是:当需要淘汰一个页面时,总是选择在最近一段时间内最久不用的页面予以淘汰。
2.代码实现
代码如下(示例):
//旧版本
def LRU(page,arr):
print(arr)
print("LRU页面置换过程为:")
result = []
loss_page = 0
sum = 0
for item in arr:
if len(result)==page:
for j in range(sum, len(arr)):
if arr[j] in result:
print("no exchange")
print("第%i页" % j, end="")
p=result[result.index(arr[j])]
del result[result.index(arr[j])]
result.insert(0,p)
print(result)
else:
del result[-1]
result.insert(0,arr[j])
loss_page += 1
print("第%i页" % j, end="")
print(result)
break
elif item in result:
print("no exchange")
p = result[result.index(item)]
del result[result.index(item)]
result.insert(0, p)
print("第%i页" % sum, end="")
print(result)
sum+=1
else:
result.insert(0,item)
loss_page+=1
print("第%i页" % sum, end="")
print(result)
sum+=1
result_page=float((loss_page)/len(arr))
print("LRU缺页率为:%.2f"%result_page)
//新版本 2024年10月16日
from collections import OrderedDict
def LRU(page_capacity, page_references):
print("LRU页面置换过程为:")
memory = OrderedDict() # 用于存储当前在内存中的页面及其访问顺序
page_faults = 0 # 记录缺页次数
for i, page in enumerate(page_references):
if page not in memory:
# 如果页面不在内存中,发生缺页
page_faults += 1
if len(memory) >= page_capacity:
# 如果内存已满,移除最近最少使用的页面(即OrderedDict中的第一个元素)
lru_page = next(iter(memory))
del memory[lru_page]
# 添加新页面到内存,并更新其访问顺序
memory[page] = None
# 更新访问顺序(将当前页面移到OrderedDict的开头)
memory.pop(page)
memory[page] = None
# 打印当前页面引用和内存状态(仅打印页面号,因为值在这里不重要)
print(f"第{i+1}页: 内存状态 {list(memory.keys())}")
# 计算缺页率
page_fault_rate = page_faults / len(page_references)
print(f"LRU缺页率为:{page_fault_rate:.2f}")
# 示例使用
page_capacity = 3 # 内存页框数
page_references = [7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2] # 页面引用序列
LRU(page_capacity, page_references)
三、OPT(最佳置换算法)
1.算法解析
算法原理从主存中移出永远不再需要的页面;如无这样的页面存在,则选择最长时间不需要访问的页面。于所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。
2.代码实现
//旧版本
def OPT(page,arr):
print("OPT页面置换过程为:")
result = []
loss_page = 0
sum = 0
for item in arr:
if len(result)==page:
for j in range(sum, len(arr)):
if arr[j] in result:
print("no exchange")
print("第%i页" % j, end="")
p = result[result.index(arr[j])]
del result[result.index(arr[j])]
result.insert(0, p)
print(result)
else:
result_number=bidui(arr[j:len(arr)],result)
for o in result:
if result_number==o:
result.remove(o)
result.append(arr[j])
loss_page += 1
print("第%i页" % j, end="")
print(result)
break
elif item in result:
print("no exchange")
print("第%i页" % sum, end="")
print(result)
sum+=1
else:
result.append(item)
loss_page+=1
print("第%i页" % sum, end="")
print(result)
sum+=1
result_page=float((loss_page)/len(arr))
print("OPT缺页率为:%.2f"%result_page)
//新版本 2024年10月16日
def find_farthest_use(page, future_pages):
"""
查找页面在未来页面引用序列中最远出现的索引。
如果页面不在未来页面序列中,则返回-1。
"""
try:
return max(index for index, f_page in enumerate(future_pages) if f_page == page)
except ValueError:
return -1
def OPT(page_capacity, page_references):
print("OPT页面置换过程为:")
memory = [] # 当前在内存中的页面列表
page_faults = 0 # 记录缺页次数
future_index = 0 # 用于跟踪未来页面引用序列的索引
for current_page in page_references:
if current_page not in memory:
# 如果页面不在内存中,发生缺页
page_faults += 1
if len(memory) < page_capacity:
# 如果内存未满,直接添加新页面
memory.append(current_page)
else:
# 如果内存已满,找出未来最远使用的页面并置换
farthest_use_indices = [find_farthest_use(page, page_references[future_index:]) for page in memory]
farthest_use_index = max(farthest_use_indices, key=lambda x: x if x != -1 else float('-inf'))
# 找到要置换的页面在内存中的索引
page_to_replace = memory[farthest_use_indices.index(farthest_use_index)]
memory.remove(page_to_replace)
memory.append(current_page)
# 打印当前页面引用和内存状态
print(f"当前页面: {current_page}, 内存状态: {memory}")
# 由于我们已经在处理当前页面,所以将未来索引向前移动
future_index += 1
# 计算缺页率
page_fault_rate = page_faults / len(page_references)
print(f"OPT缺页率为:{page_fault_rate:.2f}")
# 示例使用
page_capacity = 3 # 内存页框数
page_references = [7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2] # 页面引用序列
OPT(page_capacity, page_references)
全部代码如下
算法全部代码下载
此部分代码不做拼接,大家自行应用即可
import random
def FIFO(page,arr):
print("FIFO页面置换过程为:" )
result=[]
loss_page=0
sum=0
for item in arr:
if len(result)==page:
for j in range(sum, len(arr)):
if arr[j] in result:
print("no exchange")
print("第%i页"%j,end="")
print(result)
else:
del result[0]
result.append(arr[j])
loss_page += 1
print("第%i页" % j,end="")
print(result)
break
elif item in result:
print("no exchange")
print("第%i页" % sum,end="")
print(result)
sum+=1
else:
result.append(item)
loss_page+=1
print("第%i页" % sum,end="")
print(result)
sum+=1
result_page=float((loss_page)/len(arr))
print("FIFO缺页率为:%.2f"%result_page)
def LRU(page,arr):
print(arr)
print("LRU页面置换过程为:")
result = []
loss_page = 0
sum = 0
for item in arr:
if len(result)==page:
for j in range(sum, len(arr)):
if arr[j] in result:
print("no exchange")
print("第%i页" % j, end="")
p=result[result.index(arr[j])]
del result[result.index(arr[j])]
result.insert(0,p)
print(result)
else:
del result[-1]
result.insert(0,arr[j])
loss_page += 1
print("第%i页" % j, end="")
print(result)
break
elif item in result:
print("no exchange")
p = result[result.index(item)]
del result[result.index(item)]
result.insert(0, p)
print("第%i页" % sum, end="")
print(result)
sum+=1
else:
result.insert(0,item)
loss_page+=1
print("第%i页" % sum, end="")
print(result)
sum+=1
result_page=float((loss_page)/len(arr))
print("LRU缺页率为:%.2f"%result_page)
def bidui(param, result):
list_1 = {}
for item in param:
list_1[item]=param.index(item)
for i in result:
if i not in list_1.keys():
return i
else:
pass
return list(list_1.keys())[list(list_1.values()).index(max(list_1.values()))]
def OPT(page,arr):
print("OPT页面置换过程为:")
result = []
loss_page = 0
sum = 0
for item in arr:
if len(result)==page:
for j in range(sum, len(arr)):
if arr[j] in result:
print("no exchange")
print("第%i页" % j, end="")
p = result[result.index(arr[j])]
del result[result.index(arr[j])]
result.insert(0, p)
print(result)
else:
result_number=bidui(arr[j:len(arr)],result)
for o in result:
if result_number==o:
result.remove(o)
result.append(arr[j])
loss_page += 1
print("第%i页" % j, end="")
print(result)
break
elif item in result:
print("no exchange")
print("第%i页" % sum, end="")
print(result)
sum+=1
else:
result.append(item)
loss_page+=1
print("第%i页" % sum, end="")
print(result)
sum+=1
result_page=float((loss_page)/len(arr))
print("OPT缺页率为:%.2f"%result_page)
if __name__ == '__main__':
arr=[]
number1=int(input("请输入页面流长度"))
for i in range(number1):
arr.append(random.randint(1,number1))
print(arr)
number=int(input("请输入物理块儿数"))
FIFO(number,arr)
LRU(number, arr)
OPT(number,arr)
另附GUI算法实现界面如图所示:
GUI代码下载
# * -*- coding:utf-8 -*-
# * @Author: Go-getter Ram
import random
from tkinter import *
import time
arr = []
for i in range(20):
arr.append(random.randint(1, 5))
def gettime():
timestr = time.strftime("%H:%M:%S") # 获取当前的时间并转化为字符串
lb.configure(text=timestr) # 重新设置标签文本
root.after(1000,gettime) # 每隔1s调用函数 gettime 自身获取时间
root = Tk()
root.title('FIFO,OPT,LRU页面置换算法')
lb = Label(root,text='',fg='blue',font=("黑体",24))
lb.pack()
root.geometry('800x600') # 这里的乘号不是 * ,而是小写英文字母 x
gettime()
def run1():
page=int(inp.get())
txt.insert(END, "FIFO页面置换过程为:\n")
result = []
loss_page = 0
sum = 0
for item in arr:
if len(result) == page:
for j in range(sum, len(arr)):
if arr[j] in result:
txt.insert(END, "no exchange\n")
else:
del result[0]
result.append(arr[j])
loss_page += 1
txt.insert(END, "\n")
txt.insert(END, result)
break
elif item in result:
txt.insert(END, "no exchange\n")
txt.insert(END, result)
sum += 1
else:
result.append(item)
loss_page += 1
sum += 1
txt.insert(END, "\n")
txt.insert(END, result)
result_page = float((loss_page + page) / len(arr))
txt.insert(END, "FIFO缺页率为:%.2f\n" % result_page)
txt.insert(END, "\n")
inp.delete(0, END) # 清空输入
def run2():
page = int(inp.get())
txt.insert(END, "LRU页面置换过程为:\n")
result = []
loss_page = 0
sum = 0
for item in arr:
if len(result) == page:
for j in range(sum, len(arr)):
if arr[j] in result:
txt.insert(END, "no exchange\n")
p = result[result.index(arr[j])]
del result[result.index(arr[j])]
result.insert(0, p)
txt.insert(END, "\n")
txt.insert(END, result)
else:
del result[-1]
result.insert(0, arr[j])
loss_page += 1
txt.insert(END, "\n")
txt.insert(END, result)
break
elif item in result:
txt.insert(END, "no exchange\n")
p = result[result.index(item)]
del result[result.index(item)]
result.insert(0, p)
txt.insert(END, "\n")
txt.insert(END, result)
sum += 1
else:
result.insert(0, item)
loss_page += 1
sum += 1
txt.insert(END, "\n")
txt.insert(END, result)
result_page = float((loss_page) / len(arr))
txt.insert(END, "LRU缺页率为:%.2f" % result_page)
txt.insert(END,"\n")
inp.delete(0, END) # 清空输入
def bidui(param, result):
list_1 = {}
for item in param:
list_1[item]=param.index(item)
for i in result:
if i not in list_1.keys():
return i
else:
pass
return list(list_1.keys())[list(list_1.values()).index(max(list_1.values()))]
def run3():
page = int(inp.get())
txt.insert(END, "OPT页面置换过程为:\n")
result = []
loss_page = 0
sum = 0
for item in arr:
if len(result) == page:
for j in range(sum, len(arr)):
if arr[j] in result:
txt.insert(END, "no exchange\n")
p = result[result.index(arr[j])]
del result[result.index(arr[j])]
result.insert(0, p)
txt.insert(END, result)
txt.insert(END, "\n")
else:
result_number = bidui(arr[j:len(arr)], result)
for o in result:
if result_number == o:
result.remove(o)
result.append(arr[j])
loss_page += 1
txt.insert(END, result)
txt.insert(END, "\n")
break
elif item in result:
txt.insert(END, "no exchange\n")
txt.insert(END, result)
txt.insert(END, "\n")
sum += 1
else:
result.append(item)
loss_page += 1
sum += 1
txt.insert(END, result)
txt.insert(END, "\n")
result_page = float((loss_page) / len(arr))
txt.insert(END, "OPT缺页率为:%.2f" % result_page)
txt.insert(END,"\n")
inp.delete(0, END) # 清空输入
lb1 = Label(root, text='请输入物理块儿数:按下面三个按钮之一进行算法验证')
lb1.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.1)
str_arr=str(arr)
lb2 = Label(root, text=str_arr)
lb2.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.025)
inp = Entry(root)
inp.place(relx=0.1, rely=0.2, relwidth=0.3, relheight=0.1)
# 方法-直接调用FIFO run1()
btn1 = Button(root, text='FIFO', command=run1)
btn1.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1)
# 方法二利用 LRU 传参数调用run2()
btn2 = Button(root, text='LRU', command=lambda: run2())
btn2.place(relx=0.3, rely=0.4, relwidth=0.3, relheight=0.1)
# 方法三利用 OPT 传参数调用run3()
btn3 = Button(root, text='OPT', command=lambda: run3())
btn3.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1)
# 在窗体垂直自上而下位置60%处起,布局相对窗体高度40%高的文本框
lb_txt = Label(root, text='检验结果:')
lb_txt.place(relx=0.1, rely=0.5, relwidth=0.3, relheight=0.1)
txt = Text(root)
txt.place(rely=0.6, relheight=0.4)
root.mainloop()
<font color=#999AAA >编写不易——求赞~