当前位置:   article > 正文

操作系统(虚拟内存页面置换算法:先进先出FIFO、最佳置换OPI和最近最久未使用LRU页面置换算法)_编写程序实现: (1)先进先出页面置换算法(fifo) (2)最近最久未使用页面置换算法(lr

编写程序实现: (1)先进先出页面置换算法(fifo) (2)最近最久未使用页面置换算法(lr

目录

虚拟内存页面置换算法

一、实验环境

二、问题描述:

三、程序要求:

四、实现提示:

五、代码设计与实现

(一)程序设计

(1)最佳置换算法:

设计思想:

 部分源代码:

(2)先进先出(FIFO)页面置换算法

设计思想:

  部分源代码:

(3)LRU(Least Recently Used)置换算法

设计思想:

 部分源代码: 

总代码:

(二)运行结果

实例1:

输入:

输出:

(1)FIFO算法运行结果

(2)OPI算法运行结果

(3)LRU算法运行结果

实例2

输入:

输出:

(1)FIFO算法运行结果

(2)OPI算法运行结果

(3)LRU算法运行结果

六、总结


虚拟内存页面置换算法

一、实验环境


编译软件:pycharm

程序语言:python

二、问题描述:

        设计程序模拟先进先出FIFO、最佳置换OPI和最近最久未使用LRU页面置换算法的工作过程。假设内存中分配给每个进程的最小物理块数为m,在进程运行过程中要访问的页面个数为n,页面访问序列为P1, … ,Pn,分别利用不同的页面置换算法调度进程的页面访问序列,给出页面访问序列的置换过程,计算每种算法缺页次数和缺页率。

三、程序要求:

1)利用先进先出FIFO、最佳置换OPI和最近最久未使用LRU三种页面置换算法模拟页面访问过程。

2)模拟三种算法的页面置换过程,给出每个页面访问时的内存分配情况。

3)输入:最小物理块数m,页面个数n,页面访问序列P1, … ,Pn,算法选择1-FIFO,2-OPI,3-LRU。

4)输出:每种算法的缺页次数和缺页率。

四、实现提示:

用C++语言实现提示:

1)程序中进程调度时间变量描述如下:

  1. MaxNumber = 100
  2. PageOrder = np.zeros(MaxNumber, dtype=int) # 页面序列 创建了一个长度为MaxNumber的整数型数组,并将所有元素初始化为零。
  3. PageNum = 0 # 页面个数
  4. LackNum = 0 # 缺页次数
  5. MinBlockNum = 0 # 最小物理块数
  6. PageDisCount = np.zeros(MaxNumber, dtype=int) # 当前内存距离下一次出现的距离
  7. LRUtime = np.zeros(MaxNumber, dtype=int) # 存储队列中各个页面最近使用情况
  8. LackPageRate = 0.0 # 缺页率
  9. LackPageNum = 0 # 缺页数
  10. VirtualQueue = np.zeros(MaxNumber, dtype=int) # 虚拟队列

2)进程调度的实现过程如下:

  • 变量初始化;
  • 接收用户输入最小物理块数m,页面个数n,页面序列P1, … ,Pn,选择算法1-FIFO,2-OPI,3-LRU;
  • 根据用户选择的算法进行页面的分配和置换,输出页面置换算法的模拟过程;
  • 计算选择算法的缺页次数和缺页率;
  • 输出选择算法的缺页次数和缺页率。

五、代码设计与实现

(一)程序设计

(1)最佳置换算法
设计思想:

        按照页面号引用串的顺序,依次将物理块装入页面中,当装入下一个物理块,发现当页面已满时,将在最长时间内不再被访问的页面换出。

  • 初始化一个大小为物理块数的帧数组,用于存储当前在内存中的页面。
  • 遍历给定的引用串中的每个页面。
  • 对于每个页面,检查它是否已经在帧数组中。如果是,则跳过该页面并继续遍历下一个页面。
  • 如果该页面不在帧数组中,则需要进行页面置换。找到帧数组中以后不再使用或者在最长时间内不再被访问的页面,并用当前页面替换它。
  • 重复步骤3和4,直到遍历完引用串中的所有页面。
  • 计算缺页次数和缺页率。
 部分源代码:
  1. def OPI():
  2. #缺页数、缺页率、虚拟列表、当前内存距离下一次出现的距离
  3. global LackPageNum, LackPageRate, VirtualQueue, PageDisCount
  4. print("********* 你选择了OPI算法:********* ")
  5. print("页面置换情况如下:")
  6. initial()
  7. isInQueue = False
  8. point = 0#指向最长时间未被访问的下标
  9. for i in range(MinBlockNum, PageNum):
  10. isInQueue = PageOrder[i] in VirtualQueue
  11. if not isInQueue:
  12. LackPageNum += 1
  13. for s in range(MinBlockNum):
  14. dis = 1#表示队列每个值距离下一次访问的距离
  15. # 从页面序列的第i个位置开始找起
  16. for t in range(i, PageNum):
  17. if VirtualQueue[s] != PageOrder[t]:
  18. dis += 1
  19. else:
  20. break
  21. PageDisCount[s] = dis
  22. #指向当前虚拟列表中数据在后面最晚出现的
  23. point = np.argmax(PageDisCount)
  24. VirtualQueue[point] = PageOrder[i]
  25. display()
  26. LackPageRate = LackPageNum / PageNum
  27. print(f"缺页数LackPageNum = {LackPageNum}")
  28. print(f"缺页率LackPageRate = {LackPageRate}")
(2)先进先出(FIFO)页面置换算法
设计思想:

把一个进程已调入内存的页面按先后次序链接成一个队列,并设置一个指针,使它总是指向最老的页面;每次淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。

  • 初始化一个大小为物理块数的帧数组,用于存储当前在内存中的页面。
  • 遍历给定的引用串中的每个页面。
  • 对于每个页面,检查它是否已经在帧数组中。如果是,则跳过该页面并继续遍历下一个页面。
  • 如果该页面不在帧数组中,则需要进行页面置换。选择最早进入内存的页面进行置换,并用当前页面替换它。
  • 重复步骤3和4,直到遍历完引用串中的所有页面。
  • 计算缺页次数和缺页率。
  部分源代码:
  1. def FIFO():
  2. # 总缺页数、缺页率、虚拟队列
  3. global LackPageNum, LackPageRate, VirtualQueue
  4. print("********* 你选择了FIFO算法:********* ")
  5. print("页面置换情况如下:")
  6. initial()
  7. isInQueue = False
  8. point = 0#指向最老的页面
  9. for i in range(MinBlockNum, PageNum):
  10. isInQueue = PageOrder[i] in VirtualQueue
  11. # 如果当前页面不在队列中
  12. if not isInQueue:
  13. LackPageNum += 1#缺页数加1
  14. VirtualQueue[point] = PageOrder[i]
  15. display()
  16. point = (point + 1) % MinBlockNum
  17. #当point指向队尾后一位的时候,将point重新指向队首
  18. LackPageRate = LackPageNum / PageNum
  19. print(f"缺页数LackPageNum = {LackPageNum}")
  20. print(f"缺页率LackPageRate = {LackPageRate}")
(3)LRU(Least Recently Used)置换算法
设计思想:

赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t。当需淘汰一个页面时,选择现有页面中其t值最大的,即最久未使用的页面予以淘汰。

  • 初始化一个大小为物理块数的帧数组,用于存储当前在内存中的页面。
  • 初始化一个大小为物理块数的时间数组,用于记录每个页面最近被访问的时间。
  • 遍历给定的引用串中的每个页面。
  • 对于每个页面,检查它是否已经在帧数组中。如果是,则更新该页面在时间数组中对应的值,并跳过该页面继续遍历下一个页面。
  • 如果该页面不在帧数组中,则需要进行页面置换。选择时间数组中值最小的页面进行置换,并用当前页面替换它,同时更新该页面在时间数组中对应的值。
  • 重复步骤4和5,直到遍历完引用串中的所有页面。
  • 计算缺页次数和缺页率。
 部分源代码: 
  1. def LRU():
  2. #缺页数、缺页率、虚拟列表、存储队列中各个页面最近使用情况
  3. global LackPageNum, LackPageRate, VirtualQueue, LRUtime
  4. print("********* 你选择了LRU算法:********* ")
  5. print("页面置换情况如下:")
  6. initial()
  7. isInQueue = False
  8. point = 0#指向最长时间未被访问的下标
  9. for i in range(MinBlockNum, PageNum):
  10. isInQueue = PageOrder[i] in VirtualQueue#序列第i个页是否在队列里
  11. #如果不在队列里
  12. if not isInQueue:
  13. LackPageNum += 1#缺页数+
  14. point = np.argmax(LRUtime)#指针指向最久未使用的
  15. for j in range(MinBlockNum):
  16. if VirtualQueue[j] != VirtualQueue[point]:
  17. LRUtime[j] += 1
  18. VirtualQueue[point] = PageOrder[i]#将PageOrder[i]放入VirtualQueue中最久未使用的位置
  19. LRUtime[point] = 0
  20. display()
  21. # 如果PageOrder[i]在VirtualQueue中
  22. else:
  23. for s in range(MinBlockNum):
  24. if VirtualQueue[s] != PageOrder[i]:
  25. LRUtime[s] += 1
  26. else:
  27. LRUtime[s] = 0
  28. LackPageRate = LackPageNum / PageNum
  29. print(f"缺页数LackPageNum = {LackPageNum}")
  30. print(f"缺页率LackPageRate = {LackPageRate}")
总代码:
  1. import numpy as np
  2. MaxNumber = 100
  3. PageOrder = np.zeros(MaxNumber, dtype=int) # 页面序列 创建了一个长度为MaxNumber的整数型数组,并将所有元素初始化为零。
  4. PageNum = 0 # 页面个数
  5. LackNum = 0 # 缺页次数
  6. MinBlockNum = 0 # 最小物理块数
  7. PageDisCount = np.zeros(MaxNumber, dtype=int) # 当前内存距离下一次出现的距离
  8. LRUtime = np.zeros(MaxNumber, dtype=int) # 存储队列中各个页面最近使用情况
  9. LackPageRate = 0.0 # 缺页率
  10. LackPageNum = 0 # 缺页数
  11. VirtualQueue = np.zeros(MaxNumber, dtype=int) # 虚拟队列
  12. def input_data():
  13. global MinBlockNum, PageNum, PageOrder
  14. MinBlockNum = int(input("请输入最小物理块数: "))
  15. PageNum = int(input("请输入页面个数: "))
  16. PageOrder = list(map(int, input("请输入页面序列(以空格分隔): ").split()))
  17. print("读取数据结果如下:")
  18. print(f"最小物理块数 = {MinBlockNum}")
  19. print(f"页面个数 = {PageNum}")
  20. print("页面序列如下:")
  21. print(" ".join(map(str, PageOrder)))
  22. def initial():
  23. # 总缺页数、缺页率、当前内存距离下一次出现的距离、虚拟队列、存储队列中各个页面最近使用情况
  24. global LackPageNum, LackPageRate, PageDisCount, VirtualQueue, LRUtime
  25. LackPageNum = MinBlockNum
  26. LackPageRate = 0.0
  27. PageDisCount = np.zeros(MaxNumber, dtype=int)
  28. VirtualQueue = np.full(MaxNumber, -1, dtype=int)
  29. LRUtime = np.zeros(MinBlockNum, dtype=int)
  30. for i in range(MinBlockNum):
  31. isInQueue2 = VirtualQueue[:i].__contains__(PageOrder[i]) #用于判断PageOrder[i]是否在子列表中
  32. if not isInQueue2:
  33. VirtualQueue[i] = PageOrder[i]
  34. for k in range(i):
  35. LRUtime[k] += 1#之前的页面对应的时间+1
  36. display()
  37. else:
  38. LRUtime[i] = 0#重新更新为0,表示最近刚刚使用
  39. def FIFO():
  40. # 总缺页数、缺页率、虚拟队列
  41. global LackPageNum, LackPageRate, VirtualQueue
  42. print("********* 你选择了FIFO算法:********* ")
  43. print("页面置换情况如下:")
  44. initial()
  45. isInQueue = False
  46. point = 0#指向最老的页面
  47. for i in range(MinBlockNum, PageNum):
  48. isInQueue = PageOrder[i] in VirtualQueue
  49. # 如果当前页面不在队列中
  50. if not isInQueue:
  51. LackPageNum += 1#缺页数加1
  52. VirtualQueue[point] = PageOrder[i]
  53. display()
  54. point = (point + 1) % MinBlockNum
  55. #当point指向队尾后一位的时候,将point重新指向队首
  56. LackPageRate = LackPageNum / PageNum
  57. print(f"缺页数LackPageNum = {LackPageNum}")
  58. print(f"缺页率LackPageRate = {LackPageRate}")
  59. def OPI():
  60. #缺页数、缺页率、虚拟列表、当前内存距离下一次出现的距离
  61. global LackPageNum, LackPageRate, VirtualQueue, PageDisCount
  62. print("********* 你选择了OPI算法:********* ")
  63. print("页面置换情况如下:")
  64. initial()
  65. isInQueue = False
  66. point = 0#指向最长时间未被访问的下标
  67. for i in range(MinBlockNum, PageNum):
  68. isInQueue = PageOrder[i] in VirtualQueue
  69. if not isInQueue:
  70. LackPageNum += 1
  71. for s in range(MinBlockNum):
  72. dis = 1#表示队列每个值距离下一次访问的距离
  73. # 从页面序列的第i个位置开始找起
  74. for t in range(i, PageNum):
  75. if VirtualQueue[s] != PageOrder[t]:
  76. dis += 1
  77. else:
  78. break
  79. PageDisCount[s] = dis
  80. #指向当前虚拟列表中数据在后面最晚出现的
  81. point = np.argmax(PageDisCount)
  82. VirtualQueue[point] = PageOrder[i]
  83. display()
  84. LackPageRate = LackPageNum / PageNum
  85. print(f"缺页数LackPageNum = {LackPageNum}")
  86. print(f"缺页率LackPageRate = {LackPageRate}")
  87. def LRU():
  88. #缺页数、缺页率、虚拟列表、存储队列中各个页面最近使用情况
  89. global LackPageNum, LackPageRate, VirtualQueue, LRUtime
  90. print("********* 你选择了LRU算法:********* ")
  91. print("页面置换情况如下:")
  92. initial()
  93. isInQueue = False
  94. point = 0#指向最长时间未被访问的下标
  95. for i in range(MinBlockNum, PageNum):
  96. isInQueue = PageOrder[i] in VirtualQueue#序列第i个页是否在队列里
  97. #如果不在队列里
  98. if not isInQueue:
  99. LackPageNum += 1#缺页数+
  100. point = np.argmax(LRUtime)#指针指向最久未使用的
  101. for j in range(MinBlockNum):
  102. if VirtualQueue[j] != VirtualQueue[point]:
  103. LRUtime[j] += 1
  104. VirtualQueue[point] = PageOrder[i]#将PageOrder[i]放入VirtualQueue中最久未使用的位置
  105. LRUtime[point] = 0
  106. display()
  107. # 如果PageOrder[i]在VirtualQueue中
  108. else:
  109. for s in range(MinBlockNum):
  110. if VirtualQueue[s] != PageOrder[i]:
  111. LRUtime[s] += 1
  112. else:
  113. LRUtime[s] = 0
  114. LackPageRate = LackPageNum / PageNum
  115. print(f"缺页数LackPageNum = {LackPageNum}")
  116. print(f"缺页率LackPageRate = {LackPageRate}")
  117. def display():
  118. for i in range(MinBlockNum):
  119. if VirtualQueue[i] >= 0:
  120. print(VirtualQueue[i], end=" ")
  121. print()
  122. def main():
  123. input_data()
  124. isContinue = 1
  125. while isContinue:
  126. print("******************************************************")
  127. print("********* 请选择算法 **********")
  128. print("********* 1代表FIFO算法 **********")
  129. print("********* 2代表OPI算法 **********")
  130. print("********* 3代表LRU算法 **********")
  131. chooseAlgorithm = int(input())
  132. if chooseAlgorithm == 1:
  133. FIFO()
  134. elif chooseAlgorithm == 2:
  135. OPI()
  136. elif chooseAlgorithm == 3:
  137. LRU()
  138. else:
  139. print("请输入正确的序号进行选择:")
  140. print("********** 是否继续选择算法? **********")
  141. print("********** 输入1代表继续,输入0代表退出! **********")
  142. isContinue = int(input())
  143. print("***************************结束***************************")
  144. if __name__ == "__main__":
  145. main()

(二)运行结果

实例1:
输入:

输出:
(1)FIFO算法运行结果

(2)OPI算法运行结果

(3)LRU算法运行结果

实例2
输入:

输出:
(1)FIFO算法运行结果

(2)OPI算法运行结果

(3)LRU算法运行结果

六、总结

  1. 页面置换算法是在内存已满且需要访问的页面不在内存中时,选择一个内存中的页面换出的方法。不同的算法有不同的选择标准和效率。
  2. 最佳置换算法是选择在未来最长时间内不再被访问的页面换出,它可以保证最低的缺页率和置换率,但是它是无法实现的,因为我们无法预知未来的页面访问情况。
  3. 先进先出置换算法是选择最先进入内存的页面换出,它实现简单,但是效率不高,可能会导致经常被访问的页面被频繁地换出。
  4. 最近最久未使用置换算法是选择最久没有被访问的页面换出,它是根据过去的页面访问情况来预测未来的访问情况,但是这种预测并不一定准确,因此它的效率也不是很高。
  5. 先进先出置换算法的性能之所以差,是因为它所依据的条件是各个页面调入内存的时间,而页面调入的先后并不能反映页面的使用情况。LRU置换算法是根据页面调入内存后的使用情况做出决策的。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/687597
推荐阅读
相关标签
  

闽ICP备14008679号