在OS中,一些程序的大小超过内存的大小(比如好几十G的游戏要在16G的内存上跑),便产生了虚拟内存的概念

我们通过给每个进程适当的物理块(内存),只让经常被调用的页面常驻在物理块上,不常用的页面就放在外存,等到要用的时候再从外存调入,从而实现虚拟内存

但是因为给的每个进程的物理块大小不可能是无限的,如果该进程的物理块用完了这时候又要调入新的页面进来的话,就需要用到置换算法,其中的一个算法就叫

————>LRU(Least Recently Used)最近未使用置换算法

一、代码思想

这个算法的思想就是把已经很久没用过的页面,调出物理块然后加入新的准备调入进来的页面,对于每个物理块有两个元素

【页面号丨此页面至上次被访问以来的时间t】

我用了二维数组buffer[][2]来实现,buffer[i][0]表示的是在第i个物理块里的页面号,buffer[i][1]示的是在第i个物理块里的页面号已经有多久没用被调用过了

二,全部代码

  1. 1 #include <iostream>
  2. 2 using namespace std;
  3. 3
  4. 4 int max(int arr[][2], int n)
  5. 5 {
  6. 6 int ans = 0;
  7. 7 for (int i = 0; i < n; i++)
  8. 8 {
  9. 9 if (arr[i][1] > arr[ans][1])
  10. 10 {
  11. 11 ans = i;
  12. 12 }
  13. 13 }
  14. 14 return ans;
  15. 15 }
  16. 16
  17. 17 void check(int buffer[][2],int n)
  18. 18 {
  19. 19 for (int i = 0; i < 3; i++)
  20. 20 {
  21. 21 cout << buffer[i][0] << ' ';
  22. 22 }
  23. 23 cout << endl << "--------" << endl;
  24. 24 }
  25. 25
  26. 26 int exist_page_in_buffer(int buffer[][2], int page, int buffer_size)
  27. 27 {
  28. 28 for (int i = 0; i < buffer_size; i++)
  29. 29 {
  30. 30 if (buffer[i][0] == page)
  31. 31 {
  32. 32 return i;
  33. 33 }
  34. 34 }
  35. 35 return -1;
  36. 36 }
  37. 37
  38. 38 void one_turn(int buffer[][2], int i)
  39. 39 {
  40. 40 for (int k = 0; k < i; k++)
  41. 41 {
  42. 42 buffer[k][1]++;
  43. 43 }
  44. 44 }
  45. 45
  46. 46 void least_recently_used(int buffer[][2], int page[], int buffer_size, int page_size)
  47. 47 {
  48. 48 for (int i = 0; i < buffer_size; i++)//初始化buffer
  49. 49 {
  50. 50 buffer[i][0] = -1;
  51. 51 buffer[i][1] = 0;
  52. 52 }
  53. 53 for(int i = 0, j = 0; j < page_size;)//当页面全部调用完成时(j >= page_size),算法结束
  54. 54 {
  55. 55 //i是当前物理块中已经有多少页面了,j是已经有多少页面进行过置换了
  56. 56 if (exist_page_in_buffer(buffer, page[j], i) != -1 )//当前的页面page[j]已经存在于物理块buffer之中
  57. 57 {
  58. 58 one_turn(buffer, i); //过了一个调用周期
  59. 59 buffer[exist_page_in_buffer(buffer, page[j], i)][1] = 0;//这个page又被调用一次,所以t为0
  60. 60 check(buffer, i);
  61. 61 j++;
  62. 62 }
  63. 63 else//当前的页面page[j]不存在于物理块buffer之中
  64. 64 {
  65. 65 if (i < buffer_size)//如果物理块还没有满的话,直接加一个页面进来,就不进行置换了
  66. 66 {
  67. 67 buffer[i][0] = page[j];
  68. 68 one_turn(buffer, i);
  69. 69 check(buffer, i);
  70. 70 i++; //当前物理块中的页面个数加一,因为buffer没满,加到满为止
  71. 71 j++;
  72. 72 }
  73. 73 else//物理块已经满了,进行LRU的查找置换
  74. 74 {
  75. 75 int temp = max(buffer, buffer_size);//找一个最久没有被调用的页面进行置换
  76. 76 buffer[temp][0] = page[j];
  77. 77 one_turn(buffer, buffer_size);
  78. 78 buffer[temp][1] = 0;//这个page被置换进来调用一次,所以t为0
  79. 79 check(buffer, i);
  80. 80 j++;
  81. 81 }
  82. 82 }
  83. 83 }
  84. 84 }
  85. 85
  86. 86 int main()
  87. 87 {
  88. 88 int page[] = { 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1 };
  89. 89 int buffer[3][2];
  90. 90 int n = sizeof(page)/sizeof(int);
  91. 91 least_recently_used(buffer, page, 3, 20);
  92. 92 }

三、代码解释

首先主函数调用LRU算法,函数least_recently_used进入函数栈,page的数据来源我会在下面给出例题

  1. 1 int main()
  2. 2 {
  3. 3 int page[] = { 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1 };
  4. 4 int buffer[3][2];
  5. 5 int n = sizeof(page)/sizeof(int);
  6. 6 least_recently_used(buffer, page, 3, 20);
  7. 7 }

然后调用函数least_recently_used,首先进行对于buffer的初始化,然后进行循环调用页面,当页面全部调用完成时(j >= page_size),算法结束

  1. 1 void least_recently_used(int buffer[][2], int page[], int buffer_size, int page_size)
  2. 2 {
  3. 3 for (int i = 0; i < buffer_size; i++)//初始化buffer
  4. 4 {
  5. 5 buffer[i][0] = -1;
  6. 6 buffer[i][1] = 0;
  7. 7 }
  8. 8 for(int i = 0, j = 0; j < page_size;)//当页面全部调用完成时(j >= page_size),算法结束
  9. 9 {
  10. 10 //i是当前物理块中已经有多少页面了,j是已经有多少页面进行过置换了
  11. 11 if (exist_page_in_buffer(buffer, page[j], i) != -1 )//当前的页面page[j]已经存在于物理块buffer之中
  12. 12 {
  13. 13 one_turn(buffer, i); //过了一个调用周期
  14. 14 buffer[exist_page_in_buffer(buffer, page[j], i)][1] = 0;//这个page又被调用一次,所以t为0
  15. 15 check(buffer, i);
  16. 16 j++;
  17. 17 }
  18. 18 else//当前的页面page[j]不存在于物理块buffer之中
  19. 19 {
  20. 20 if (i < buffer_size)//如果物理块还没有满的话,直接加一个页面进来,就不进行置换了
  21. 21 {
  22. 22 buffer[i][0] = page[j];
  23. 23 one_turn(buffer, i);
  24. 24 check(buffer, i);
  25. 25 i++; //当前物理块中的页面个数加一,因为buffer没满,加到满为止
  26. 26 j++;
  27. 27 }
  28. 28 else//物理块已经满了,进行LRU的查找置换
  29. 29 {
  30. 30 int temp = max(buffer, buffer_size);//找一个最久没有被调用的页面进行置换
  31. 31 buffer[temp][0] = page[j];
  32. 32 one_turn(buffer, buffer_size);
  33. 33 buffer[temp][1] = 0;//这个page被置换进来调用一次,所以t为0
  34. 34 check(buffer, i);
  35. 35 j++;
  36. 36 }
  37. 37 }
  38. 38 }
  39. 39 }

再解释一下每个函数的作用

max,这个就是从buffer里找到最久没用调用过的页面,返回他的所在物理块的位置

  1. 1 int max(int arr[][2], int n)
  2. 2 {
  3. 3 int ans = 0;
  4. 4 for (int i = 0; i < n; i++)
  5. 5 {
  6. 6 if (arr[i][1] > arr[ans][1])
  7. 7 {
  8. 8 ans = i;
  9. 9 }
  10. 10 }
  11. 11 return ans;
  12. 12 }

check,检查函数的运行情况

  1. 1 void check(int buffer[][2],int n)
  2. 2 {
  3. 3 for (int i = 0; i < 3; i++)
  4. 4 {
  5. 5 cout << buffer[i][0] << ' ';
  6. 6 }
  7. 7 cout << endl << "--------" << endl;
  8. 8 }

exist_page_in_buffer,每次调入页面时,都先检查一遍这个页面有没有已经被调入到当前的物理块中,如果在,返回此页面在物理块中的位置,如果不在,返回-1

  1. 1 int exist_page_in_buffer(int buffer[][2], int page, int buffer_size)
  2. 2 {
  3. 3 for (int i = 0; i < buffer_size; i++)
  4. 4 {
  5. 5 if (buffer[i][0] == page)
  6. 6 {
  7. 7 return i;
  8. 8 }
  9. 9 }
  10. 10 return -1;
  11. 11 }

one_turn,过了一个调用周期(主要就是为了让其他的page距离上次被调用的时间t++)

  1. 1 void one_turn(int buffer[][2], int i)
  2. 2 {
  3. 3 for (int k = 0; k < i; k++)
  4. 4 {
  5. 5 buffer[k][1]++;
  6. 6 }
  7. 7 }

四、书上例题和运行结果

运算结果如下

7 -1 -1
--------
7 0 -1
--------
7 0 1
--------
2 0 1
--------
2 0 1
--------
2 0 3
--------
2 0 3
--------
4 0 3
--------
4 0 2
--------
4 3 2
--------
0 3 2
--------
0 3 2
--------
0 3 2
--------
1 3 2
--------
1 3 2
--------
1 0 2
--------
1 0 2
--------
1 0 7
--------
1 0 7
--------
1 0 7
--------

LRU(Least Recently Used)最近未使用置换算法--c实现的更多相关文章

  1. 深入理解【缺页中断】及FIFO、LRU、OPT这三种置换算法

    缺页中断(英语:Page fault,又名硬错误.硬中断.分页错误.寻页缺失.缺页中断.页故障等)指的是当软件试图访问已映射在虚拟地址空间中,但是目前并未被加载在物理内存中的一个分页时,由中央处理器的 ...

  2. 页面置换算法——最近最久未使用算法(c语言实现)

    操作系统实验:用C语言编程实现最近最久未使用置换算法(LRU) 最近最久未使用置换算法(LRU),全称Least Recently Used,是一种页面置换算法. 对于在内存中但又不用的数据块(内存块 ...

  3. 页面置换算法(最佳置换算法、FIFO置换算法、LRU置换算法、LFU置换算法)

    页面置换产生的原因是:分页请求式存储管理(它是实现虚拟存储管理的方法之一,其中一个特性是多次性-->多次将页面换入或换出内存) 效果最好的页面置换算法:最佳置换算法 比较常用的页面置换算法有:F ...

  4. 操作系统笔记(六)页面置换算法 FIFO法 LRU最近最久未使用法 CLOCK法 二次机会法

    前篇在此: 操作系统笔记(五) 虚拟内存,覆盖和交换技术 操作系统 笔记(三)计算机体系结构,地址空间.连续内存分配(四)非连续内存分配:分段,分页 内容不多,就不做index了. 功能:当缺页中断发 ...

  5. 页面置换算法-LRU(Least Recently Used)c++实现

    最近最久未使用(LRU)置换算法 #include <iostream> #include <cstdio> #include <cstring> #include ...

  6. 操作系统页面置换算法(opt,lru,fifo,clock)实现

    选择调出页面的算法就称为页面置换算法.好的页面置换算法应有较低的页面更换频率,也就是说,应将以后不会再访问或者以后较长时间内不会再访问的页面先调出. 常见的置换算法有以下四种(以下来自操作系统课本). ...

  7. (待续)C#语言中的动态数组(ArrayList)模拟常用页面置换算法(FIFO、LRU、Optimal)

    目录 00 简介 01 算法概述 02 公用方法与变量解释 03 先进先出置换算法(FIFO) 04 最近最久未使用(LRU)算法 05 最佳置换算法(OPT) 00 简介 页面置换算法主要是记录内存 ...

  8. 操作系统 页面置换算法LRU和FIFO

    LRU(Least Recently Used)最少使用页面置换算法,顾名思义,就是替换掉最少使用的页面. FIFO(first in first out,先进先出)页面置换算法,这是的最早出现的置换 ...

  9. FIFO、LRU、OPT这三种置换算法的缺页次数

    考虑下述页面走向: 1,2,3,4,2,1,5,6,2,1,2,3,7,6,3,2,1,2,3,6 当内存块数量分别为3时,试问FIFO.LRU.OPT这三种置换算法的缺页次数各是多少? 答:缺页定义 ...

随机推荐

  1. 职场中究竟什么是ownership,你是一个有ownership的人吗?

    在互联网行业,我们经常用一个标准去评价一个人,这个标准就是ownership.一个有ownership的员工往往会被认为是出色的,被委以重任,从此升职加薪.而一个被打上了没有ownership的人,往 ...

  2. redis 常用基本命令

    redis 常用基本命令 redis-cli 启动set  键  值       # 存储 单条数据  # set 'zsj' 'bab' get  键        # 通过键获取值   # get ...

  3. 淘宝|蚂蚁|菜鸟|盒马|嘀嘀|饿了么面经(已拿多个offer)

    上一篇的同学拿到了bigo和腾讯的offer,这一次的分享来自两位同学的面试综合,他们分别拿到了菜鸟.嘀嘀.盒马的多个offer,由于面试的时间跨度时间太长,且面试的部门太多,只能回忆到具体的面试题, ...

  4. ipad做windows副屏

    利用iPad做windows的触摸显示屏 由于ios与windows不兼容,所以利用软件进行 主要的软件有三款:duet display:spacedesk:Splashtop Wired XDisp ...

  5. react第二十单元(react+react-router-dom+redux综合案例2)

    第二十单元(react+react-router-dom+redux综合案例2) #课程目标 #知识点 #授课思路 #案例和作业

  6. 如何push一个docker镜像到DockerHub上

    在DockerHub上创建账号:https://hub.docker.com/ 这里我的账号是firewarm 本地下载镜像(这里拿alpine做示例),并为镜像打tag [root@host-30 ...

  7. pytorch固定BN层参数

    背景:基于PyTorch的模型,想固定主分支参数,只训练子分支,结果发现在不同epoch相同的测试数据经过主分支输出的结果不同. 原因:未固定主分支BN层中的running_mean和running_ ...

  8. 一.C语言概述

    C语言的起源 贝尔实验室的Dennis Ritchie在1972年开发了C,当时他正与ken Thompson一起设计UNIX操作系统,然而,C并不是完全由Ritchie构想出来的.它来自Thomps ...

  9. Linux(Centos7)安装、使用 Docker

    一.Linux(CentOS7) 上安装 docker 1.docker 是什么? docker 是一种 虚拟化容器技术,一个开源的应用容器引擎. 基于镜像,可以秒级启动各种容器(运行一次镜像就生成一 ...

  10. java实体类和json串字段名称不一致或者与map中字段名称不一致使用注解转化

    package yuanCheng; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List ...