Python实现页面置换算法

Python实现页面置换算法

FIFO LRU OPT



页面置换算法:

在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。


一、FIFO(先进先出置换算法)

1.算法解析

算法原理:当需要淘汰一个页面时,总是选择驻留主存时间最长的页面进行淘汰,即先进入主存的页面先淘汰。其理由是:最早调入主存的页面不再被使用的可能性最大。

如图所示(示例):

FIFO先进先出示例

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 >编写不易——求赞~

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

干中学冲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值