操作系统虚拟内存中的四种典型页替换算法(OPT,LRU,FIFO,Clock)

       页面置换:在地址映射过程中,若在页面中发现所要访问的页面不再内存中,则产生缺页中断(page fault)。当发生缺页中断时操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。

  

典型的置换算法有四种,如下所示:

 OPT:最佳替换算法(optional replacement。替换下次访问距当前时间最长的页。opt算法需要知道操作系统将来的事件,显然不可能实现,只作为一种衡量其他算法的标准。

 分析:(F表示页帧最初填满时出现page fault)

 a.需要页面2,内存中还有空闲位置,直接加入页面2

 b.需要页面3,内存中还有空闲位置,直接加入页面3

 c.需要页面2,内存中已经存在页面2,不加入任何页面

 d.需要页面1,内存中还有空闲位置,直接加入页面1

 e.需要页面5,页面2距离下次访问之间的距离为1,页面3距离下次访问距离为3,页面1没有下次访问(距离为无穷             大),所以替换掉页面1

 f.需要页面2,内存中已经存在页面2,不加入任何页面

 g.需要页面4,页面2,3,5距离下次访问的距离依次是3,2,1,所以替换掉页面2

 h.需要页面5,内存中存在页面5,不改变

 i.需要页面3,内存中存在页面3,不改变

 j.需要页面2,页面4,3,5距离下次访问的距离依次是无穷大,无穷大,1,此时按照先后顺序替换掉页面4

 k.需要页面5,内存中存在页面5,不改变

 L.需要页面2,内存中存在页面2,不改变


LRU:最近最少使用(Least Recently Used).替换上次使用距离当前最远的页。根据局部性原理:替换最近最不可能 访问到的页。性能最接近OPT,但难以实现。可以维护一个关于访问页的栈或者给每个页添加最后访问的时间标签,但开销都很大。

 分析:(F表示页帧最初填满时出现page fault)

 a.需要页面2,内存中还有空闲位置,直接加入页面2

 b.需要页面3,内存中还有空闲位置,直接加入页面3

 c.需要页面2,内存中已经存在页面2,不加入任何页面,这里重置了2的最近历史访问记录

 d.需要页面1,内存中还有空闲位置,直接加入页面1

 e.需要页面5,页面2,3,1距离最近一次历史访问的距离依次为2,3,1(步骤c中重置了2的访问记录).所以替换掉页        面3.

 f.需要页面2,内存中已经存在页面2,不加入任何页面,重置页面2的访问记录

 g.需要页面4,页面2,5,1距离最近一次历史访问的距离依次是1,2,3,所以替换掉页面1

 h.需要页面5,内存中存在页面5,不改变,重置页面5的访问记录

 i.需要页面3,页面2,5,4距离最近一次历史访问的距离依次为3,1,2,所以替换掉页面2

 j.需要页面2,页面3,5,4距离最近一次历史访问的距离依次为1,2,3,所以替换掉页面4

 k.需要页面5,内存中存在页面5,不改变

 L.需要页面2,内存中存在页面2,不改变


FIFO:先进先出(First In First Out),将页面看做一个循环缓冲区,按循环方式替换。这是实现最为简单的算法,隐含的逻辑是替换驻留在内存时间最长的页。但由于一部分程序或数据在整个程序的生命周期中使用频率很高,所以会导致反复的换入换出。

分析:

策略极为简单,如果内存中有空闲位置,则直接替换。否则,可以先想象有一个指针,开始指向第一个位置,没发生替换则指针位置不变,每次需要替换时替换指针所指的位置,然后将指针向后移动一位(若指针位于最后,则移动到内存第一个位置)。


Clock:时钟替换算法(Clock),给每个页帧关联一个使用位。当该页第一次装入内存或者被重新访问到时,将使用位置为1。每次需要替换时,查找使用位被置为0的第一个帧进行替换。在扫描过程中,如果碰到使用位为1的帧,将使用位置为0,在继续扫描。如果所谓帧的使用位都为0,则替换第一个帧。

 分析:(表示说明:页面:“2(1)”表示页面2的使用位为1。"p(n)"表示扫描指针指向第n个的位置)

首先扫描指针p指向第一个帧位置p(1),每次发生替换(或者内存中有空闲位置时进行的替换),指针加1。

 a.需要页面2,内存中还有空闲位置,直接加入页面2,得到2(1),p(2).

 b.需要页面3,内存中还有空闲位置,直接加入页面3,得到2(1),3(1),p(3).

 c.需要页面2,内存中已经存在页面2,不加入任何页面,且这不是页面2的第一次放置,得到2(1),3(1),p(3).

 d.需要页面1,直接加入页面1,得到2(1),3(1),1(1),p(1)

 e.需要页面5,第一轮扫描将2,3,1的使用位都置为0,然后替换掉页面2,得到5(1),3(0),1(0),p(2)

 f.需要页面2,扫描到页面3的使用位为0,所以替换页面3,得到5(1),2(1),1(0),p(3)

 g.需要页面4,扫描到页面1的使用位为0,所以替换页面1,得到5(1),2(1),4(1),p(1)

 h.需要页面5,内存中存在页面5,不改变,得到5(1),2(1),4(1),p(1)

 i.需要页面3,第一轮扫描将5,2,4的使用位都置为0,然后替换到页面5,得到3(1),2(0),4(0),p(2)

 j.需要页面2,扫描到页面2的使用位为0,由于2被重新访问,所以将2的使用位置为1,得到3(1),2(1),4(0),p(2),注       意此时由于未发生页错误,p指针不加1.只是重置了使用位(记住:每次新加入的页使用位都为1)

 k.需要页面5,第一轮扫描将2的使用位置为0,替换掉页面4,得到3(1),2(0),5(1),p(1)

 L.需要页面2,重置页面2的使用位为1,指针p不变,得到3(1),2(1),5(1),p(1)

总结:

1.内存中不存在页面n,而内存中有空闲位置时,直接加入页面n(1),p加1

2.内存中不存在页面n,且内存中没有空闲位置时,发生替换n(1), p加1

3.内存中存在页面n,,p不变,将页面n重置为n(1)(不管页面n之前使用位为1或0)


改进后的时钟算法:设置使用位u,修改位m

1.最近未被访问,未被修改(u=0,m=0)

2.最近被访问,未被修改(u=1,m=0)

3.最近未被访问,被修改(u=0,m=1)

4.最近被访问,被修改(u=1,m=1)

a.从指针当前位置开始扫描,不修改使用位,对找到的第一个(u=0,m=0)进行替换

b.如果a失败,找到第一个(u=0,m=1)进行替换,扫描过程中,将使用位u置为0

c,如果b失败,此时指针回到起始位置,且所有帧的使用位为0,重复步骤a,如果有必要,重复步骤b,直到找到为止



一起学习,一起进步,欢迎访问我的博客:http://blog.csdn.net/wanghao109


  • 31
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
以下是Python实现的页面置换算法OPTFIFOLRUclock算法的程序: ```python # -*- coding: utf-8 -*- # 定义常量 PAGE_NUM = 10 # 面数 MEMORY_SIZE = 3 # 内存块数 # 生成随机面序列 page_seq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 随机打乱面序列 import random random.shuffle(page_seq) # 初始化内存 memory = [] # OPT算法 def opt(page): if page not in memory: if len(memory) < MEMORY_SIZE: memory.append(page) else: max_index = 0 max_page = memory[0] for i in range(MEMORY_SIZE): if memory[i] not in page_seq: max_page = memory[i] break elif page_seq.index(memory[i]) > max_index: max_index = page_seq.index(memory[i]) max_page = memory[i] memory[memory.index(max_page)] = page # FIFO算法 def fifo(page): if page not in memory: if len(memory) < MEMORY_SIZE: memory.append(page) else: memory.pop(0) memory.append(page) # LRU算法 def lru(page): if page in memory: memory.remove(page) else: if len(memory) >= MEMORY_SIZE: memory.pop(0) memory.append(page) # clock算法 def clock(page): global clock_pointer if page not in memory: if len(memory) < MEMORY_SIZE: memory.append(page) else: while True: if memory[clock_pointer][1] == 0: memory[clock_pointer] = [page, 1] clock_pointer = (clock_pointer + 1) % MEMORY_SIZE break else: memory[clock_pointer][1] = 0 clock_pointer = (clock_pointer + 1) % MEMORY_SIZE # 执行页面置换算法 for i in range(PAGE_NUM): opt(page_seq[i]) #fifo(page_seq[i]) #lru(page_seq[i]) #clock(page_seq[i]) # 输出每次置换后的内存状态 print("第%d次置换:" % (i+1), end=" ") for j in range(MEMORY_SIZE): if j < len(memory): print(memory[j], end=" ") else: print("-", end=" ") print() # 输出缺率 print("缺率:", (PAGE_NUM - len(memory)) / PAGE_NUM) ``` 程序先定义了常量`PAGE_NUM`和`MEMORY_SIZE`,分别表示面数和内存块数。然后生成随机的面序列,打乱顺序,用于模拟面的访问。接着定义了全局变量`memory`和`clock_pointer`,分别表示当前内存状态和clock算法的指针位置。 程序实现了四种页面置换算法OPTFIFOLRUclock算法。每次访问一个面时,会根据当前算法的规则来决定是否需要将该面加入内存,如果内存已满,则选择一个面进行替换。每次置换后会输出当前的内存状态,以便观察算法的效果。最后输出缺率。 注释提到的FIFOLRU算法的实现也在程序给出,可以通过注释掉OPT算法的执行语句,取消注释FIFOLRUclock算法的执行语句,来测试不同算法的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值