• 操作系统 页面置换算法(C++实现)


    1. 最佳(Optimal)置换算法

    1.1 算法原理

      其选择淘汰的页面将是以后永不使用的,或许是在最长时间内不再被访问的页面。采用最佳置换算法通常可以保证获得最低的缺页率。但由于人们目前还无法预知,一个进程在内存的若干个界面中,哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的,但可以利用它来评价其他算法。现举例如下:

      最佳置换算法可以用来评价其他算法。假定系统为某进程分配了三个物理块,并考虑有以下页面号引用串:
          7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1

    进程运行时,先将7, 0, 1三个页面依次装入内存。进程要访问页面2时,产生缺页中断,根据最佳置换算法,选择第18次访问才需调入的页面7予以淘汰。然后,访问页面0时,因为已在内存中所以不必产生缺页中断。访问页面3时又会根据最佳置换算法将页面1淘汰……依此类推,如图3-26所示。从图中可以看出釆用最佳置换算法时的情况。

      可以看到,发生缺页中断的次数为9,页面置换的次数为6。

    访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
    1 7 7 7 2   2   2     2     2       7    
    2   0 0 0   0   4     0     0       0    
    3     1 1   3   3     3     1       1    
    缺页否  √                      

    1.2 实现代码函数

     1 void Optimal(vector<int> PageOrder, vector<vector<int> > &Simulate, int &PageNum,int &LackNum, int m, int n){
     2     vector<bool> found(n,false); // 记录页面中是否存在
     3     vector<int> lump; // 物理块
     4 
     5     for(int i = 0; i < n; found[PageOrder[i]] = true, i ++){
     6         //物理块中不存在
     7         if( !found[PageOrder[i]] ){
     8             // 物理块未满时
     9             if(lump.size() < m){
    10                 lump.push_back(PageOrder[i]);
    11             }
    12             // 物理块满需要置换
    13             else{
    14                 int temp, max = 0;
    15                 for(int j = 0; j < lump.size(); j ++){
    16                     int count = i;
    17                     for(; count < n + 1; count ++)
    18                         if(PageOrder[count] == lump[j]) break;
    19                     if(count > max){
    20                         max = count;temp = j; // 记录当前最远页面序号
    21                     }
    22                 }
    23                 found[lump[temp]] = false;
    24                 lump[temp] = PageOrder[i];
    25             }
    26             for(int j = 0; j < lump.size(); j ++)
    27                 Simulate[i].push_back(lump[j]);
    28             LackNum ++; //访问页面失败
    29         }
    30         //物理块中存在
    31         else
    32             PageNum ++; //访问页面成功
    33     }
    34 }

    2. 先进先出(FIFO)置换算法

    2.1 算法原理

      是最简单的页面置换算法。这种算法的基本思想是:当需要淘汰一个页面时,总是选择驻留主存时间最长的页面进行淘汰,即先进入主存的页面先淘汰。其理由是:最早调入主存的页面不再被使用的可能性最大。 

    访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
    1 7 7 7 2   2 2 4 4 4 0     0 0     7 7 7
    2   0 0 0   3 3 3 2 2 2     1 1     1 0 0
    3     1 1   1 0 0 0 3 3     3 2     2 2 1
    缺页否          

      这里仍用上面的实例,釆用FIFO算法进行页面置换。进程访问页面2时,把最早进入内存的页面7换出。然后访问页面3时,再把2, 0, 1中最先进入内存的页换出。由图 3-27可以看出,利用FIFO算法时进行了 12次页面置换,比最佳置换算法正好多一倍。

    2.2 实现代码函数

     1 void FIFO(vector<int> PageOrder, vector<vector<int> > &Simulate, int &PageNum,int &LackNum, int m, int n){
     2     vector<bool> found(n,false);
     3     vector<int> lump;
     4     queue<int> buffer; //用来记录先后顺序
     5 
     6     for(int i = 0; i < n; found[PageOrder[i]] = true, i ++){
     7         if( !found[PageOrder[i]] ){
     8             if(lump.size() < m){
     9                 lump.push_back(PageOrder[i]);
    10                 buffer.push(PageOrder[i]);
    11             }
    12             else{
    13                 for(int j = 0; j < lump.size(); j ++)
    14                     if(lump[j] == buffer.front()){
    15                         found[lump[j]] = false;
    16                         lump[j] = PageOrder[i]; //替换
    17                         buffer.push(PageOrder[i]);
    18                         buffer.pop(); break;
    19                     }
    20             }
    21             for(int j = 0; j < lump.size(); j ++)
    22                 Simulate[i].push_back(lump[j]);
    23             LackNum ++;
    24         }
    25         else
    26             PageNum ++;
    27     }
    28 }

    3. 最近最久未使用(LRU)算法

    3.1 算法原理

      这种算法的基本思想是:利用局部性原理,根据一个作业在执行过程中过去的页面访问历史来推测未来的行为。它认为过去一段时间里不曾被访问过的页面,在最近的将来可能也不会再被访问。所以,这种算法的实质是:当需要淘汰一个页面时,总是选择在最近一段时间内最久不用的页面予以淘汰。 

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

    访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
    1 7 7 7 2   2   4 4 4 0     1   1   1    
    2   0 0 0   0   0 0 3 3     3   0   0    
    3     1 1   3   3 2 2 2     2   2   7    
    缺页否                

      实际上,LRU算法根据各页以前的情况,是“向前看”的,而最佳置换算法则根据各页以后的使用情况,是“向后看”的。

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

    3.2 实现代码函数

     1 void LRU(vector<int> PageOrder, vector<vector<int> > &Simulate, int &PageNum,int &LackNum, int m, int n){
     2     vector<int> count(n,0); // 记录页面存在时间
     3     vector<bool> found(n,false);
     4     vector<int> lump;
     5 
     6     for(int i = 0; i < PageOrder.size(); count[PageOrder[i]] = i,found[PageOrder[i]] = true, i ++){
     7         if( !found[PageOrder[i]] ){
     8             if( lump.size() < m){
     9                 lump.push_back(PageOrder[i]);
    10             }
    11             else{
    12                 int temp, max = 0;
    13                 // 计录当前物理块中存在最长时间的元素
    14                 for(int j = 0; j < lump.size(); j ++){
    15                     if(i - count[lump[j]] > max){
    16                         max = i - count[lump[j]];
    17                         temp = j;
    18                     }
    19                 }
    20                 found[lump[temp]] = false;
    21                 lump[temp] = PageOrder[i];
    22             }
    23             for(int j = 0; j < lump.size(); j ++)
    24                 Simulate[i].push_back(lump[j]);
    25             LackNum ++;
    26         }
    27         else
    28             PageNum ++;
    29     }
    30 }

    4. 时钟(CLOCK)置换算法

    4.1 算法原理

      LRU算法的性能接近于OPT,但是实现起来比较困难,且开销大;FIFO算法实现简单,但性能差。所以操作系统的设计者尝试了很多算法,试图用比较小的开销接近LRU的性能,这类算法都是CLOCK算法的变体。


      简单的CLOCK算法是给每一帧关联一个附加位,称为使用位。当某一页首次装入主存时,该帧的使用位设置为1;当该页随后再被访问到时,它的使用位也被置为1。对于页替换算法,用于替换的候选帧集合看做一个循环缓冲区,并且有一个指针与之相关联。当某一页被替换时,该指针被设置成指向缓冲区中的下一帧。当需要替换一页时,操作系统扫描缓冲区,以查找使用位被置为0的一帧。每当遇到一个使用位为1的帧时,操作系统就将该位重新置为0;如果在这个过程开始时,缓冲区中所有帧的使用位均为0,则选择遇到的第一个帧替换;如果所有帧的使用位均为1,则指针在缓冲区中完整地循环一周,把所有使用位都置为0,并且停留在最初的位置上,替换该帧中的页。由于该算法循环地检查各页面的情况,故称为CLOCK算法,又称为最近未用(Not Recently Used, NRU)算法。

      CLOCK算法的性能比较接近LRU,而通过增加使用的位数目,可以使得CLOCK算法更加高效。在使用位的基础上再增加一个修改位,则得到改进型的CLOCK置换算法。这样,每一帧都处于以下四种情况之一:

    1. 最近未被访问,也未被修改(u=0, m=0)。
    2. 最近被访问,但未被修改(u=1, m=0)。
    3. 最近未被访问,但被修改(u=0, m=1)。
    4. 最近被访问,被修改(u=1, m=1)。


    算法执行如下操作步骤:

    1. 从指针的当前位置开始,扫描帧缓冲区。在这次扫描过程中,对使用位不做任何修改。选择遇到的第一个帧(u=0, m=0)用于替换。
    2. 如果第1)步失败,则重新扫描,查找(u=0, m=1)的帧。选择遇到的第一个这样的帧用于替换。在这个扫描过程中,对每个跳过的帧,把它的使用位设置成0。
    3. 如果第2)步失败,指针将回到它的最初位置,并且集合中所有帧的使用位均为0。重复第1步,并且如果有必要,重复第2步。这样将可以找到供替换的帧。


      改进型的CLOCK算法优于简单CLOCK算法之处在于替换时首选没有变化的页。由于修改过的页在被替换之前必须写回,因而这样做会节省时间。

  • 相关阅读:
    bzoj3729-Gty的游戏【Splay,博弈论】
    pkusc2021游记
    P4922-[MtOI2018]崩坏3?非酋之战!【dp】
    P5782-[POI2001]和平委员会【2-SAT】
    CF1511G-Chips on a Board【倍增】
    noip范围
    [LGOJ5558]心上秋(倍增)
    学习笔记——动态DP
    [NOIP校内集训]不正常的国家
    [BZOJ4712]洪水(树链剖分+DP)
  • 原文地址:https://www.cnblogs.com/john1015/p/13021237.html
Copyright © 2020-2023  润新知