当前位置:   article > 正文

页面置换算法(FIFO,OPT,LRU)_fifo算法

fifo算法

FIFO(First In First Out)

先进先出页面置换算法(First In First Out,FIFO)是一种简单的页面置换算法,它依据页面进入主存储器的先后顺序进行页面置换。FIFO算法是一种非常直观的页面置换算法,它将最早进入主存储器的页面作为最先置换的页面。

具体来说,FIFO算法维护一个先进先出的页面队列,当一个页面需要调入主存储器时,它被加入队列的末尾。当需要置换页面时,FIFO算法选择队列头部的页面进行置换。这样,最先进入主存储器的页面总是最先被置换出去,而最后进入主存储器的页面总是保留在主存储器中。

FIFO算法的优点是实现简单,适用于对于页面访问顺序没有特别要求的场景,缺点是无法判断哪些页面是频繁使用的,而只是根据时间进行置换,可能会导致一些常用的页面被频繁置换,从而影响系统的性能。

  1. int FIFO(int n){
  2. //创建长度为n的空间来表示已经存储进去了
  3. int *tmp=new int[n];
  4. int i=0;
  5. //统计页面交换的次数
  6. int exchange=0;
  7. //初始化标记成-1是,说明空间没有被占用
  8. for(i=0;i<n;i++){
  9. tmp[i]=-1;
  10. }
  11. for(i=0;i<ppLength;i++){
  12. //index返回小于0说明tmp中没有要查找的元素
  13. if(index(tmp,n,processPage[i])<0){
  14. //说明tmp还有位置
  15. if(index(tmp,n,-1)>=0){
  16. int pos=index(tmp,n,-1);
  17. //直接把进程的页面填进来了
  18. tmp[pos]=processPage[i];
  19. }else{
  20. //没有位置了就把最先到的移出去
  21. int j=0;
  22. for(j=0;j<n-1;j++){
  23. tmp[i]=tmp[i+1];
  24. }
  25. //把新进来的加到数组的末尾
  26. tmp[n-1]=processPage[i];
  27. //记录交换的次数
  28. exchange++;
  29. }
  30. }
  31. }
  32. return exchange;
  33. }
  34. //查找数组arr中有没有target元素
  35. int index(int *arr,int size,int target){
  36. int i=0;
  37. for(i=0;i<size;i++){
  38. //查找到元素,返回其下标
  39. if(arr[i]==target){
  40. return i;
  41. }
  42. }
  43. //没有查到则返回-1
  44. return -1;
  45. }

我原本是这样写的,但是这种写法到后面没有输出了,可能是数组需要经常的移动元素,浪费的大量的时间,这个其实可以不移动数组元素,类似循环队列的思想,来实现移动队列元素的效果。

  1. //先进先出置换算法
  2. int FIFO(int n){
  3. //记录页面交换的次数
  4. int exchange=0;
  5. int head,tail,count;
  6. //记录队头,队尾,以及当前队列中的元素个数
  7. head=tail=count=0;
  8. int *arr=new int[n];
  9. int i=0;
  10. for(i=0;i<ppLength;i++){
  11. //查找物理内存中是否含有该页面
  12. if(index(arr,head,tail,processPage[i],n+1)<0){
  13. //判断物理内存是否填满,没有就直接添加进来
  14. if(count<n){
  15. arr[tail]=processPage[i];
  16. tail=(tail+1)%(n+1);
  17. count++;
  18. exchange++;
  19. }else{
  20. //“移除”最先进来的页面
  21. head=(head+1)%(n+1);
  22. //添加新页面
  23. arr[tail]=processPage[i];
  24. tail=(tail+1)%(n+1);
  25. exchange++;
  26. }
  27. }
  28. }
  29. return exchange;
  30. }
  31. //查找数组arr中有没有target元素[head,tail]
  32. int index(int *arr,int head,int tail,int target,int size){
  33. while(head!=tail){
  34. if(arr[head]==target){
  35. return head;
  36. }
  37. head=(head+1)%size;
  38. }
  39. return -1;
  40. }

代码思路分析:首先判断页面是否已经存在物理内存中,然后就判断内存里面还有没有空间,如果还有空间就直接加到末尾即可,要注意的这个tail就是末尾,head表示开头,然后通过取余实现循环队列的效果。

OPT(Optimal)

最佳置换算法(Optimal,OPT)是一种最理想的页面置换算法,它会选择未来最长时间内不使用的页面进行置换。但是很遗憾,实际上无法完全地预测出未来哪个页面最长时间内不会被使用,因此最佳置换算法只能算是一种理论上的算法。

具体来说,最佳置换算法维护一个未来页面使用情况的列表,当需要置换页面时,它会选择未来最长时间内不会被使用的页面进行置换。因此,最佳置换算法需要预测未来页面使用情况,通常通过分析页面的历史使用情况来进行预测。

最佳置换算法的优点是最理想的,可以保证置换出去的页面未来不会被再次访问,因此是页面置换算法的一个理论上的最佳选择。缺点是需要精确预测未来的内存访问模式,而这通常是不可能做到的。实际应用中,最佳置换算法很少被使用,通常使用一些近似算法来优化系统的性能。

  1. //最佳置换算法
  2. int OPT(int n){
  3. int *arr=new int[n];
  4. int exchange=0;//统计页面交换的次数
  5. int count=0;//记录当前物理内存中已经添加的数量
  6. int i;
  7. for(i=0;i<ppLength;i++){
  8. //查找物理内存中是否含有该页面
  9. if(index(arr,0,count,processPage[i],n+1)<0){
  10. if(count<n){
  11. //直接添加到最后
  12. arr[count]=processPage[i];
  13. count++;
  14. exchange++;
  15. }else{
  16. //寻找最久页面不用的下标
  17. int pos=index(arr,count,processPage[i],i);
  18. //更新内存中的页面
  19. arr[pos]=processPage[i];
  20. exchange++;
  21. }
  22. }
  23. }
  24. return exchange;
  25. }
  26. //查找数组arr中有没有target元素[head,tail]
  27. int index(int *arr,int head,int tail,int target,int size){
  28. while(head!=tail){
  29. if(arr[head]==target){
  30. return head;
  31. }
  32. head=(head+1)%size;
  33. }
  34. return -1;
  35. }
  36. //查找最久不用页面对应在数组中元素的下标
  37. int index(int *arr,int size,int target,int pos){
  38. int farthestDistance=0;//记录最远距离的页面位置
  39. int sub=0;//记录最远不用页面在物理内存(arr)中对应的元素下标
  40. bool flag=false;//标记该页面是否被找到
  41. int i,j;
  42. for(i=0;i<size;i++){
  43. flag=false;
  44. j=pos+1;//从pos之后的位置开始找最久不用的页面
  45. while(j<ppLength&&!flag){
  46. //找到页面
  47. if(arr[i]==processPage[j]){
  48. flag=true;
  49. //判断是否还有更久不用的页面
  50. if((j-pos)>farthestDistance){
  51. //更新最远距离
  52. farthestDistance=j-pos;
  53. sub=i;
  54. }
  55. }
  56. j++;
  57. }
  58. if(!flag){
  59. //可以取到的最近不用页面的距离
  60. farthestDistance=ppLength-pos;
  61. sub=i;
  62. }
  63. }
  64. return sub;
  65. }

代码思路分析:首先的判断还是和前面一样,就是对于查找应该置换页面的方式不同,通过遍历之后的页面来判断哪个是最久才会被使用的将他淘汰,记录最晚出现的页面在内存中对应的下标进行淘汰即可。

LRU(Least Recently Used)

最近最久未使用(Least Recently Used,LRU)是一种常用的页面置换算法。LRU算法的基本思想是,根据页面的使用历史,置换最近最久未使用的页面。

具体来说,LRU算法维护一个页面使用时刻的列表,当需要置换页面时,它会选择最近最久未使用的页面进行置换。为了实现这个算法,可以使用一个链表来维护已经调入内存的页面,每次页面被访问时,将其移到链表的头部,最近访问的页面总是在头部。

这种算法的优点是相对简单,不需要像最佳置换算法一样需要精确地预测未来的内存访问模式。它完全按照页面的历史使用情况来进行置换,可以有效地利用已经调入内存的页面资源,提高了系统性能。缺点是实现比较复杂,需要维护一个按访问时间排序的列表,因此会增加一定的计算负担。

总的来说,LRU算法是一种比较优秀的页面置换算法,被广泛应用于操作系统和数据库等领域。

  1. //最久未使用置换算法
  2. int LRU(int n){
  3. //物理内存
  4. int *arr=new int[n];
  5. int *help=new int[n];//记录页面被访问的情况,数值大的被交换
  6. int exchange=0;//统计页面交换的次数
  7. int count=0;//记录当前物理内存中已经添加的数量
  8. int i,j;
  9. //最开始页面都没被调用
  10. for(i=0;i<n;i++){
  11. help[i]=0;
  12. }
  13. for(i=0;i<ppLength;i++){
  14. for(j=0;j<n;j++){
  15. //每次有新的页面都加一,不管有没有发生置换,表示页面这次没有被使用
  16. help[j]++;
  17. }
  18. //查找物理内存中是否含有该页面
  19. if(index(arr,0,count,processPage[i],n+1)<0){
  20. //判断物理内存是否填满,没有就直接添加进来
  21. if(count<n){
  22. //直接添加到最后,并标记为0
  23. arr[count]=processPage[i];
  24. help[count]=0;
  25. count++;
  26. exchange++;
  27. }else{
  28. //查找最久没有使用的下标,并进行交换
  29. int pos=index(help,n);
  30. arr[pos]=processPage[i];
  31. help[pos]=0;
  32. exchange++;
  33. }
  34. }else{
  35. //虽然不用置换,但是也要标记,说明该页面被使用
  36. int pos=index(arr,0,count,processPage[i],n+1);
  37. help[pos]=0;
  38. }
  39. }
  40. return exchange;
  41. }
  42. //查找数组arr中有没有target元素[head,tail]
  43. int index(int *arr,int head,int tail,int target,int size){
  44. while(head!=tail){
  45. if(arr[head]==target){
  46. return head;
  47. }
  48. head=(head+1)%size;
  49. }
  50. return -1;
  51. }
  52. //返回数组arr中最大值对应的下标
  53. int index(int *arr,int size){
  54. int max=0;
  55. int sub;
  56. int i;
  57. for(i=0;i<size;i++){
  58. //记录最大值以及对应的下标
  59. if(max<arr[i]){
  60. sub=i;
  61. max=arr[i];
  62. }
  63. }
  64. return sub;
  65. }

代码思路分析:通过一个数组来记录对应页面没有使用的次数,然后就淘汰最久没有使用的哪个即可,要注意的是,当页面在内存中已经存在的时候也要更新记录次数的数组,标记成0就意味着改页面被使用了。

 注意我这里的话重载了三个index函数,都是查找下标,但是里面还是有差别的。

  1. #include<iostream>
  2. using namespace std;
  3. //所有进程的页面走向,这个设置成全局变量就减少了参数的传递
  4. int processPage[]={7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1};
  5. int ppLength=sizeof(processPage)/sizeof(int);
  6. //相关函数的声明
  7. int FIFO(int i);//先进先出置换算法
  8. int OPT(int i);//最佳置换算法
  9. int LRU(int i);//最久未使用置换算法
  10. //查找数组arr中有没有target元素
  11. int index(int *arr,int head,int tail,int target,int size);
  12. int index(int *arr,int size,int target,int pos);
  13. int index(int *arr,int size);
  14. int main(){
  15. int i=0;
  16. //先把所有的页面打印一遍
  17. cout<<"访问页为:";
  18. for(i=0;i<ppLength;i++){
  19. cout<<processPage[i]<<" ";
  20. }
  21. cout<<endl<<endl;
  22. //系统给进程的物理块数
  23. for(i=1;i<=7;++i){
  24. //输出相关信息 ,这个输出可能会造成输出混乱
  25. cout<<"驻留集大小 "<<i<<endl;
  26. cout<<"FIFO 缺页次数 "<<FIFO(i)<<endl;
  27. cout<<"OPT 缺页次数 " <<OPT(i)<<endl;
  28. cout<<"LRU 缺页次数 "<<LRU(i)<<endl;
  29. cout<<endl;
  30. }
  31. return 0;
  32. }
  33. //先进先出置换算法
  34. int FIFO(int n){
  35. //记录页面交换的次数
  36. int exchange=0;
  37. int head,tail,count;
  38. //记录队头,队尾,以及当前队列中的元素个数
  39. head=tail=count=0;
  40. int *arr=new int[n];
  41. int i=0;
  42. for(i=0;i<ppLength;i++){
  43. //查找物理内存中是否含有该页面
  44. if(index(arr,head,tail,processPage[i],n+1)<0){
  45. //判断物理内存是否填满,没有就直接添加进来
  46. if(count<n){
  47. arr[tail]=processPage[i];
  48. tail=(tail+1)%(n+1);
  49. count++;
  50. exchange++;
  51. }else{
  52. //“移除”最先进来的页面
  53. head=(head+1)%(n+1);
  54. //添加新页面
  55. arr[tail]=processPage[i];
  56. tail=(tail+1)%(n+1);
  57. exchange++;
  58. }
  59. }
  60. }
  61. return exchange;
  62. }
  63. //最佳置换算法
  64. int OPT(int n){
  65. int *arr=new int[n];
  66. int exchange=0;//统计页面交换的次数
  67. int count=0;//记录当前物理内存中已经添加的数量
  68. int i;
  69. for(i=0;i<ppLength;i++){
  70. //查找物理内存中是否含有该页面
  71. if(index(arr,0,count,processPage[i],n+1)<0){
  72. if(count<n){
  73. //直接添加到最后
  74. arr[count]=processPage[i];
  75. count++;
  76. exchange++;
  77. }else{
  78. //寻找最久页面不用的下标
  79. int pos=index(arr,count,processPage[i],i);
  80. //更新内存中的页面
  81. arr[pos]=processPage[i];
  82. exchange++;
  83. }
  84. }
  85. }
  86. return exchange;
  87. }
  88. //最久未使用置换算法
  89. int LRU(int n){
  90. //物理内存
  91. int *arr=new int[n];
  92. int *help=new int[n];//记录页面被访问的情况,数值大的被交换
  93. int exchange=0;//统计页面交换的次数
  94. int count=0;//记录当前物理内存中已经添加的数量
  95. int i,j;
  96. //最开始页面都没被调用
  97. for(i=0;i<n;i++){
  98. help[i]=0;
  99. }
  100. for(i=0;i<ppLength;i++){
  101. for(j=0;j<n;j++){
  102. //每次有新的页面都加一,不管有没有发生置换,表示页面这次没有被使用
  103. help[j]++;
  104. }
  105. //查找物理内存中是否含有该页面
  106. if(index(arr,0,count,processPage[i],n+1)<0){
  107. //判断物理内存是否填满,没有就直接添加进来
  108. if(count<n){
  109. //直接添加到最后,并标记为0
  110. arr[count]=processPage[i];
  111. help[count]=0;
  112. count++;
  113. exchange++;
  114. }else{
  115. //查找最久没有使用的下标,并进行交换
  116. int pos=index(help,n);
  117. arr[pos]=processPage[i];
  118. help[pos]=0;
  119. exchange++;
  120. }
  121. }else{
  122. //虽然不用置换,但是也要标记,说明该页面被使用
  123. int pos=index(arr,0,count,processPage[i],n+1);
  124. help[pos]=0;
  125. }
  126. }
  127. return exchange;
  128. }
  129. //查找数组arr中有没有target元素[head,tail]
  130. int index(int *arr,int head,int tail,int target,int size){
  131. while(head!=tail){
  132. if(arr[head]==target){
  133. return head;
  134. }
  135. head=(head+1)%size;
  136. }
  137. return -1;
  138. }
  139. //查找最久不用页面对应在数组中元素的下标
  140. int index(int *arr,int size,int target,int pos){
  141. int farthestDistance=0;//记录最远距离的页面位置
  142. int sub=0;//记录最远不用页面在物理内存(arr)中对应的元素下标
  143. bool flag=false;//标记该页面是否被找到
  144. int i,j;
  145. for(i=0;i<size;i++){
  146. flag=false;
  147. j=pos+1;//从pos之后的位置开始找最久不用的页面
  148. while(j<ppLength&&!flag){
  149. //找到页面
  150. if(arr[i]==processPage[j]){
  151. flag=true;
  152. //判断是否还有更久不用的页面
  153. if((j-pos)>farthestDistance){
  154. //更新最远距离
  155. farthestDistance=j-pos;
  156. sub=i;
  157. }
  158. }
  159. j++;
  160. }
  161. if(!flag){
  162. //可以取到的最近不用页面的距离
  163. farthestDistance=ppLength-pos;
  164. sub=i;
  165. }
  166. }
  167. return sub;
  168. }
  169. //返回数组arr中最大值对应的下标
  170. int index(int *arr,int size){
  171. int max=0;
  172. int sub;
  173. int i;
  174. for(i=0;i<size;i++){
  175. //记录最大值以及对应的下标
  176. if(max<arr[i]){
  177. sub=i;
  178. max=arr[i];
  179. }
  180. }
  181. return sub;
  182. }

这个最开始写的时候是把框架写成这样,结果发现和理想的输出不符合。不知道是不是我写错的问题,我的思路就行先把他输出就行,每次输出的函数都是返回一个0.后面看到一个可能原因。

for循环中有异步操作导致数据顺序错乱的问题 - 码农教程 (manongjc.com)icon-default.png?t=N7T8http://www.manongjc.com/detail/25-jxvuwkozmptrftp.html

  1. #include<iostream>
  2. using namespace std;
  3. //所有进程的页面走向,这个设置成全局变量就减少了参数的传递
  4. int processPage[]={7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1};
  5. int ppLength=sizeof(processPage)/sizeof(int);
  6. //相关函数的声明
  7. int FIFO(int i);//先进先出置换算法
  8. int OPT(int i);//最佳置换算法
  9. int LRU(int i);//最久未使用置换算法
  10. int main(){
  11. int i=0;
  12. //先把所有的页面打印一遍
  13. cout<<"访问页为:";
  14. for(i=0;i<ppLength;i++){
  15. cout<<processPage[i]<<" ";
  16. }
  17. cout<<endl<<endl;
  18. //系统给进程的物理块数
  19. for(i=1;i<=7;++i){
  20. //输出相关信息
  21. cout<<"驻留集大小 "<<i<<endl;
  22. cout<<"FIFO 缺页次数 "<<FIFO(i)<<endl;
  23. cout<<"OPT 缺页次数 " <<OPT(i)<<endl;
  24. cout<<"LRU 缺页次数 "<<LRU(i)<<endl;
  25. cout<<endl;
  26. }
  27. return 0;
  28. }
  29. //先进先出置换算法
  30. int FIFO(int i){
  31. return 0;
  32. }
  33. //最佳置换算法
  34. int OPT(int i){
  35. return 0;
  36. }
  37. //最久未使用置换算法
  38. int LRU(int i){
  39. return 0;
  40. }

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

闽ICP备14008679号