• 操作系统实验三虚拟存储器管理之模拟页面置换算法(FIFO&LRU)


    文章目录

    一、概述

     (1)置换算法

     (2)缺页率与命中率

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

       (1)定义

       (2)示例

     (3)Belady异常

     三、最近最久未使用置换算法(LRU)

    (1)定义

    (2)示例

    四、FIFO&LRU置换算法的模拟

       (1)流程图

     (2)完整代码

     (3)实验结果


    一、概述

    (1)置换算法

            进程运行时,若其访问的页面不在内存中而需要将其调入,但内存已经无空闲空间时,就需要从内存中调出一页程序或者数据,送入磁盘的对换区。

            选择调出页面的算法就称为页面置换算法。常见的页面置换算法有以下四种:

    • 最佳置换算法(OPT)
    • 先进先出页面置换算法(FIFO)
    • 最近最久未使用置换算法(LRU)
    • 时钟置换算法(CLOCL)

    (2)缺页率与命中率

            当前访问的页面不在内存中时,此时发生缺页中断,选择合适的页面置换算法来从内存中调出一页程序或者数据,送入磁盘的对换区,与当前要访问的页面进行置换,从而满足当前的访问需求。这种情况就叫缺页,相反,如果当前访问的页面在内存中时,即为命中。二者有如下关系:

    • 缺页率+命中率=1
    • 缺页率=缺页次数/总页面访问次数
    • 命中率=命中次数/总页面访问次数

    本次实验重点是模拟先进先出和最近最久未使用算法的执行过程。


    二、先进先出置换算法(FIFO

    (1)定义

            优先淘汰那些最早进入内存的页面,即淘汰在内存中驻留时间最久的页面。该算法实现简单,只需把已调入内存的页面根据先后次序链接成队列,设置一个指针总是指向最老的页面。

    (2)示例

    假定系统为某个进程分配了3个物理块,访问页面依次如下:7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1

    按照FIFO算法, 当依次访问页面7,0,1时,由于都不在内存中发生缺页中断,因为有3个物理块且内存空闲,所以可以不用置换页面直接将这三个页面依次放入内存中;当访问页面2时,由于不在内存中,发生缺页中断,此时按照FIFO置换算法将内存中最早进入内存的页面7与2置换,让2进入内存,后面以此类推。

    (3)Belady异常

            分配给进程的物理块增多,但是缺页率却不减反增的现象被称之为Belady异常。如图:

     当进程有3个物理块时,缺页次数为9,缺页率为75%

     当进程有4个物理块时,缺页次数为10,缺页率为83.33%

     另外,只有FIFO算法会出现Belady异常,其它算法不会出现这种情况!


     三、最近最久未使用置换算法(LRU

    (1)定义

            选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问。该算法为每个页面设置一个访问字段,用来记录页面自上次被访问以来所经历的时间,淘汰页面时选择现有页面中值最大的予以淘汰。

    (2)示例

            再对上面的例子采用LRU算法进行页面置换,如图3.25所示。进程第一次对页面 2访问时,将最近最久未被访问的页面7置换出去。然后在访问页面3时,将最近最久未使用的页面1换出。

            LRU算法的性能较好,但需要寄存器和栈的硬件支持。LRU是堆栈类的算法。理论上可以证明,堆栈类算法不可能出现Belady异常。FIFO 算法基于队列实现,不是堆栈类算法。


    四、FIFO&LRU置换算法的模拟

    (1)流程图

     (2)完整代码

    1. /*
    2. 虚拟存储器之页面置换算法的模拟
    3. 测试数据1:20个访问的页面 3个物理块:
    4. 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
    5. 测试数据2:10个访问页面 2个物理块
    6. 4 2 3 0 3 2 1 2 0 1
    7. */
    8. #include
    9. #define phy 100
    10. #define page 100//页面最大数
    11. #define phyBlock 100//物理块最大数
    12. int phyBlockNum;//物理块的数量
    13. int pageNum;//页面数量
    14. int pageNumStrList[page];//保存页面号引用串
    15. //初始化队列
    16. void initializeList(int list[], int number)
    17. {
    18. for (int i = 0; i < number; i++)
    19. {
    20. list[i] = -1;
    21. }
    22. }
    23. //展示当前队列状态
    24. void showList(int list[], int number)
    25. {
    26. for (int i = 0; i < number; i++)
    27. {
    28. printf("%2d", list[i]);
    29. }
    30. printf("\n");
    31. }
    32. //展示当前系统内存状态
    33. void showMemoryList(int list[], int phyBlockNum)
    34. {
    35. for (int i = 0; i < phyBlockNum; i++)
    36. {
    37. if (list[i] == -1)
    38. {
    39. break;
    40. }
    41. printf(" |%d|\t", list[i]);
    42. }
    43. printf("\n");
    44. }
    45. //页面置换结果分析统计
    46. void informationCount(int missingCount, int replaceCount, int pageNum)
    47. {
    48. printf("---------------------------结果分析--------------------------\n");
    49. printf("缺页次数:%d\n", missingCount);
    50. double a=(double)missingCount/pageNum;//计算缺页率以百分号形式表示
    51. printf("缺页率:%.2f%%\n", a*100);
    52. double result = (double)(pageNum - missingCount) / (double)pageNum;
    53. printf("置换次数:%d\n", replaceCount);
    54. printf("------------------------------------------------------------\n");
    55. }
    56. //寻找该页面下次要访问的位置
    57. int getNextPosition(int currentPage, int currentPosition, int strList[], int pageNum)
    58. {
    59. for (int i = currentPosition + 1; i < pageNum; i++)
    60. {
    61. if (strList[i] == currentPage)
    62. {
    63. return i;
    64. }
    65. }
    66. return 100;
    67. }
    68. //FIFO:先进先出置换算法
    69. void replacePageByFIFO(int memoryList[], int phyNum, int strList[], int pageNum) {
    70. int replaceCount = 0; //置换次数
    71. int missingCount = 0; //缺页次数
    72. int pointer = 0; //记录当前最早进入内存的下标
    73. int isVisited = 0;//记录当前页面的访问情况: 0表示未访问,1表示已访问
    74. for (int i = 0; i < pageNum; i++) {
    75. isVisited = 0;
    76. //判断是否需要置换,内存已满且需要访问的页面不在内存中
    77. for (int j = 0; j < phyNum; j++) {
    78. if (memoryList[j] == strList[i]) {
    79. //1.该页面已经存在内存中
    80. //修改访问情况
    81. isVisited = 1;
    82. //修改访问时间
    83. printf("%d\t", strList[i]);
    84. printf("\n");
    85. break;
    86. }
    87. if (memoryList[j] == -1) {
    88. //2.页面不在内存中且内存未满则直接存入即可
    89. memoryList[j] = strList[i];
    90. //修改访问情况
    91. isVisited = 1;
    92. missingCount++;
    93. printf("%d\t", strList[i]);
    94. showMemoryList(memoryList, phyNum);
    95. break;
    96. }
    97. }
    98. //当前页面还未被访问过,需要进行页面置换
    99. if (!isVisited) {
    100. //直接把这个页面存到所记录的下标中
    101. memoryList[pointer] = strList[i];
    102. pointer++; //下标指向下一个
    103. //如果到了最后一个,将下标归零
    104. if (pointer > phyNum - 1) {
    105. pointer = 0;
    106. }
    107. missingCount++;
    108. replaceCount++;
    109. printf("%d\t", strList[i]);
    110. showMemoryList(memoryList, phyNum);
    111. }
    112. }
    113. informationCount(missingCount, replaceCount, pageNum);
    114. }
    115. //LRU:最近最久未使用置换算法
    116. void replacePageByLRU(int memoryList[], int phyNum, int strList[], int pageNum) {
    117. int replaceCount = 0;//置换次数
    118. int missingCount = 0; //缺页次数
    119. int timeRecord[phy]; //记录内存中最近一次访问至今的时间
    120. initializeList(timeRecord, phyNum);
    121. int isVisited = 0;
    122. //记录已经在内存中的页面数量
    123. int pageCount = 0;
    124. for (int i = 0; i < pageNum; i++) {
    125. isVisited = 0;
    126. //时间加一
    127. for (int p = 0; p < pageCount; p++) {
    128. if (memoryList[p] != -1) {
    129. timeRecord[p] ++;
    130. }
    131. }
    132. //是否需要置换
    133. for (int j = 0; j < phyNum; j++) {
    134. if (memoryList[j] != -1) {
    135. timeRecord[j] ++;
    136. }
    137. if (memoryList[j] == strList[i]) {
    138. //该页面已经存在内存中
    139. //修改访问情况
    140. isVisited = 1;
    141. //重置访问时间
    142. timeRecord[j] = -1;
    143. printf("%d\t", strList[i]);
    144. printf("\n");
    145. break;
    146. }
    147. if (memoryList[j] == -1) {
    148. //页面不在内存中且内存未满,直接存入
    149. memoryList[j] = strList[i];
    150. pageCount++;
    151. //修改访问情况
    152. isVisited = 1;
    153. //修改访问时间
    154. timeRecord[j]++;
    155. missingCount++;
    156. printf("%d\t", strList[i]);
    157. showMemoryList(memoryList, phyNum);
    158. break;
    159. }
    160. }
    161. //不在内存中,则需要进行页面置换
    162. if (!isVisited) {
    163. //1.遍历时间记录表,寻找最久未访问的页面所在的内存下标
    164. int max = 0;
    165. for (int k = 0; k < phyNum; k++) {
    166. if (timeRecord[max] < timeRecord[k]) {
    167. max = k;
    168. }
    169. }
    170. //2.将该位置的页面换出
    171. memoryList[max] = strList[i];
    172. timeRecord[max] = -1;
    173. missingCount++;
    174. replaceCount++;
    175. printf("%d\t", strList[i]);
    176. showMemoryList(memoryList, phyNum);
    177. }
    178. }
    179. informationCount(missingCount, replaceCount, pageNum);
    180. }
    181. //测试
    182. int main(int argc, const char* argv[])
    183. {
    184. printf("------------------虚拟存储器之页面置换算法------------------\n");
    185. printf("请输入内存的物理块数量:");
    186. scanf("%d", &phyBlockNum);
    187. //生成内存队列
    188. int memoryList[phyBlock];
    189. //初始化内存状态
    190. initializeList(memoryList, phyBlockNum);
    191. //showMemoryList(memoryList,phyBlockNum);
    192. printf("请输入要访问的页面总数:");
    193. scanf("%d", &pageNum);
    194. printf("请输入要访问的页面号:");
    195. for (int i = 0; i < pageNum; i++) {
    196. scanf("%d", &pageNumStrList[i]);
    197. }
    198. printf("------------------------------------------------------------\n");
    199. int chose;
    200. while (1)
    201. {
    202. printf("★请选择你要执行的操作:(1.FIFO算法 2.LRU算法 3.退出):");
    203. scanf("%d", &chose);
    204. switch (chose)
    205. {
    206. case 1:
    207. printf("------------------------------------------------------------\n");
    208. printf("页面号\t");
    209. for(int i=0;i
    210. printf("物理块%d\t",i+1);
    211. }
    212. printf("\n");
    213. replacePageByFIFO(memoryList, phyBlockNum, pageNumStrList, pageNum);
    214. //重新初始化内存
    215. initializeList(memoryList, phyBlockNum);
    216. break;
    217. case 2:
    218. printf("------------------------------------------------------------\n");
    219. printf("页面号\t");
    220. for(int i=0;i
    221. printf("物理块%d\t",i+1);
    222. }
    223. printf("\n");
    224. replacePageByLRU(memoryList, phyBlockNum, pageNumStrList, pageNum);
    225. //重新初始化内存
    226. initializeList(memoryList, phyBlockNum);
    227. break;
    228. default:
    229. printf("退出成功");
    230. return 0;
    231. break;
    232. }
    233. }
    234. return 0;
    235. }

    (3)实验结果

    最后, 如果本文内容对你有所帮助,记得点赞收藏哈。

  • 相关阅读:
    imx8 yocto增加文件
    Java高级特性-泛型方法
    10年经验总结:数据分析师7种工具,因果分析划重点!
    reticulate | R-python调用 | 安装及配置 | conda文件配置
    oracle 设置表空间 表空间操作
    LINE Verda Programming Contest (AtCoder Beginner Contest 263) A~E 题解
    谷粒商城 高级篇 (八) --------- 缓存使用
    LeetCode|股票问题|121. 买卖股票的最佳时机、122. 买卖股票的最佳时机 II、123. 买卖股票的最佳时机 III
    ROS1和ROS2的区别
    centos7下编译安装freeswitch及常见编译问题的解决
  • 原文地址:https://blog.csdn.net/qq_52487066/article/details/127773232