操作系統 頁面置換算法(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算法之處在於替換時首選沒有變化的頁。由於修改過的頁在被替換之前必須寫回,因而這樣做會節省時間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM