1. 程式人生 > >六、頁面置換演算法

六、頁面置換演算法

頁面置換演算法

  • 功能:當出現缺頁異常,需調入新頁面而記憶體已滿時,置換演算法選擇被置換的物理頁面
  • 目標:儘可能減少缺頁中斷(頁面的換入換出)次數。具體來說,把未來不再使用的或短期內較少使用的頁面換出,通常只能在區域性性原理指導下依據過去的統計資料來進行預測。 
  • 頁面鎖定(frame locking):用於描述必須常駐記憶體的作業系統的關鍵部分,或時間關鍵的應用程序(time-critical)。實現的方法是在頁表中新增鎖定標誌位(lock bit)

比較不同的頁面置換演算法: 設定一個實驗環境,記錄一個程序對頁訪問的軌跡。 
虛擬地址跟蹤(3,0) (1,9) (4,1)…… 
偏移可忽略,只用頁號生成頁面軌跡3,1,4 …… 


模擬一個頁面置換的行為並且記錄產生缺頁的數量,越少越好 

區域性頁面置換演算法

置換頁面的選擇範圍僅限於當前程序佔用的物理頁面

最優頁面置換演算法
  • 基本思路:當一個缺頁中斷髮生時,對於儲存在記憶體當中的每一個邏輯頁面,計算在它的也一次訪問之間,還需等待多長的時間,從中選擇等待時間最長的那個,作為被置換的頁面。
  • 這只是一整理想的情況,在實際的系統中是無法實現的,因為作業系統無法直到每一個頁面要等待多長時間以後才會再次被訪問。
  • 可用作其他演算法的評價的依據(在一個模擬器上執行某個程式,並記錄每一次的頁面的訪問情況,在第二遍執行時間可使用最優演算法)

                   

d最遠,被置換出,e被加入。

先進先出演算法first-in first-out ,FIFO 
  • 基本思路:選擇在記憶體中駐留時間最長的頁面並淘汰之。具體來說:OS維護著一個連結串列,記錄了所有記憶體當中的邏輯頁面。從連結串列的排序順序來看,鏈首頁面的駐留時間最長,鏈尾頁面的駐留時間最短。當發生一個頁面中斷時,把鏈首頁面淘汰出局,把新的頁面新增到連結串列的末尾。 
  • 效能較差,調出的頁面可能是經常要訪問的頁面(駐留時間長,本身就說明可能常用),有belady現象(給的物理頁幀越多反而缺頁越頻繁),FIFO演算法很少單獨使用。 

                  

最近最久未使用演算法(least recently used, LRU 
  • 思路:當一個缺頁中斷髮生時,選擇最久未使用的那個頁面,並淘汰之。
  • 它是對最優置換演算法的近似,以過去推未來。根據程式的區域性性原理,即在最近一小段時間(最近幾條指令),如果某些頁面被頻繁訪問,那麼在將來的一小段時間內,它們還可能再一次被頻繁訪問。反之,如果在過去某些頁面長時間未被訪問,那麼將來它們還可能會長時間地得不到訪問。
  •                

LRU演算法需要記錄各個頁面使用時間的先後順序,開銷比較大,兩種可能的實現方法。 

  • 系統維護一個頁面連結串列,最近剛使用的頁面作為首結點,最久未使用的頁面作為尾結點,每次訪問記憶體時,找到相應的頁面,把它從連結串列中摘下來,再移動到連結串列之首,每次缺頁中斷髮生時,淘汰連結串列末尾的頁面。
  • 設定一個活動頁面堆疊:當訪問某頁時,將此頁號入棧頂,並去除棧內的重複頁。當需要淘汰一個頁面時,總是選擇棧底的頁面,它就是最久未使用的。

                     

時鐘頁面置換演算法
  •  Clock 頁面置換演算法——LRU的近似,對FIFO的改進 
  • 基本思路:需要用到頁表項的訪問位(access bit),當一個頁面被裝入記憶體時,把該位初始化為0,然後如果這個頁被訪問(讀/寫)時,硬體把它置為1. 
  • 把各個頁面組織成環形連結串列(類似鐘錶面),把指標指向最老的頁面(最先進來);
  • 當發生一個缺頁中斷,考察指標所指向的最老的頁面,若它的訪問為為0,則立即淘汰。若訪問為1,則把該位置為0,然後指標往下移動一格。如此下去,直到找到被淘汰的頁面,然後把指標移動到它的下一格。

                            

頁號0和1的訪問位被置0,頁號為1的頁表項被替換,訪問位置1,指標指向下一個位置頁號7

        

產生4次缺頁中斷,比LRU差一些,在實踐的系統中和LRU接近。

二次機會法(或者enhanced clock)
  • 思路:減少修改頁的缺頁處理開銷
  • 修改Clock演算法,使它允許髒頁總是在一次時鐘頭掃描中保留下來,同時使用髒位(dity bit,也叫寫位)和使用位來指導置換

                  

      

產生三次缺頁中斷,與LRU接近,優先替換隻讀頁,對於可寫頁減少被替換概率,對硬碟讀寫次數少。

最不常用演算法(least frequently used,LFU)
  • 基本思路:當一個缺頁中斷髮生時,選擇訪問次數最少的那個頁面,並淘汰之
  • 實現方法:對每個頁面設定一個訪問計數器,每當一個頁面被訪問時,該頁面的訪問計數器加1,淘汰計數值最小的那個頁面
  • LRU/LFU區別:LRU考察的是多久未訪問,時間越短越值得留在記憶體,LFU是訪問次數/頻度,次數越多越好。 

反例:一個頁面在程序開始時使用的很多,但以後就不使用了。此時LFU就不適用了。把時間也考慮進去,在一段時間內考察LFU。比如,定期把次數暫存器右移一位。 

Belady現象
  • Belady現象:在採用FIFO演算法時,有時會出現的物理頁面數增加,缺頁率反而提高的異常現象。
  • Belady現象原因:FIFO演算法的置換特徵與程序訪問記憶體的動態特徵是矛盾的,與置換演算法的目標是不一致的(即替換較少使用的頁面),因此,被它置換出去的頁面不一定是程序不會訪問的。
LRU、FIFO與Clock的比較
  • LRU和FIFO本質都是先進先出的思路,但LRU是針對頁面的最近訪問時間來進行排序,所以需要在每一次頁面訪問的時候動態的調整各個頁面之間的先後順序(每一個頁面的最近訪問時間變了);而FIFO針對頁面進入記憶體的時間來進行排序,這個時間是固定不變的,所以頁面之間的先後順序是固定不變的。如果程式區域性性,則LRU會很好。如果記憶體中所有頁面都沒有被訪問過會退化為FIFO(如頁面進入記憶體後沒有被訪問,最近訪問時間與進入記憶體的時間相同)。 
  • LRU演算法效能較好,但系統開銷較大;FIFO演算法的系統的開銷較小,但可能發生Belady現象。因此,擇衷的辦法就是Clock演算法,在每一次頁面訪問時,它不必去動態調整頁面在連結串列中的順序,而僅僅是做一個標記,等待發生缺頁中斷的時候,再把它移動到連結串列的末尾。對於記憶體當中未被訪問的頁面,Clock演算法的表現與LRU一樣好,而對於那些曾經訪問過的頁面,它不能像LRU那樣記住它們的準確訪問順序。

全域性頁面置換演算法

全域性頁面置換演算法置換頁面的選擇範圍是所有可換出的物理頁面

全域性置換需要解決的問題:

  • 程序在不同階段的記憶體需求是變化的

  • 分配給程序的記憶體也需要在不同階段有所變化

  • 全域性置換演算法需要確定分配給程序的物理頁面數

工作集模型

前面介紹的各種頁面置換演算法都是基於一個前提,即程式的區域性性原理。

  • 如果區域性性原理不成立,那各種演算法都沒啥區別,也就沒什麼意義。比如程序對邏輯頁面的訪問順序是單調遞增,那麼在頁面數有限的前提下,不管哪種演算法都會缺頁中斷。 
  • 如果區域性性原理成立,那麼如何證明它的存在,如何對它進行定量分析,這就是工作集模型。

工作集:一個程序當前使用的邏輯頁面集合 ,可以用一個二元函式W(t,Δ)表示。

  • t是當前執行時刻
  • Δ是工作集視窗 (working-set window),一個定長的頁面訪問的時間視窗
  • W(t,Δ)就是在當前時刻t之前的Δ時間內所有訪問頁面組成的集合,在隨t不斷更新
  • | W(t,Δ)|是工作集的大小即頁面數目。 

                    

工作集的變化:程序開始後,隨著訪問新頁面逐步建立較穩定的工作集,當記憶體訪問的區域性性區域的位置大致穩定時,工作集大小也大致穩定。區域性性區域的位置改變時,工作集快速擴張和收縮過渡到下一個穩定值

           

常駐集:在當前時刻,程序實際駐留在記憶體當中的頁面集合。

  • 工作集是程序在執行過程中固有性質,常駐集取決於系統分配給程序的物理頁面數目和所採用的置換演算法。
  • 如果一個程序的整個工作集在記憶體中,即常駐集包含工作集,那麼程序會很順利的執行,而不會造成太多的缺頁中斷(直到工作集發生劇烈變動,從而過度到另一階段)
  • 當程序常駐集大小達到某個數目後,再分配更多的物理頁面,缺頁率也不會明顯下降。可以把多出來的物理頁面分給其他程式了。
工作集置換演算法: 
  • 思路:換出不在工作集中的頁面,
  • 當前時刻前τ個記憶體訪問的頁引用是工作集,τ被稱為視窗大小

  • 實現方法:維護視窗內的訪存頁面連結串列,訪存時,換出不在工作集的頁面;更新訪存連結串列。缺頁時,換入頁面;更新訪存連結串列

                     

老的頁會隨著時間不斷的換出,不管是否有缺頁中斷。確保物理頁幀始終有空餘的,給其他程式提供記憶體,在整個系統層面保證缺頁率降低。

缺頁率頁面置換演算法 

可變分配策略:常駐集大小可變 。例如:每個程序在剛開始執行的時候,根據程式的大小給它分配一定數目的物理頁面,然後再程式的執行過程中,再動態的調整常駐集的大小

  • 可採用全域性頁面置換的方式,當發生一個缺頁中斷時,被置換的頁面可以在其他程序中,各個併發程序競爭地使用物理頁面。
  • 效能較好,但增加了系統開銷 
  • 具體實現:可以使用缺頁率置換演算法(PFF, page fault frequency)動態調整常駐集的大小。

缺頁率:缺頁次數/ 記憶體訪問次數或缺頁平均時間間隔的倒數

影響缺頁率的因素:

  • 頁面置換演算法
  • 分配給程序的物理頁面數目(越多越小)
  • 頁面本身的大小(頁面大則會小)
  • 程式設計方法(區域性性好就會小)

通過調節常駐集大小,使每個程序的缺頁率保持在一個合理的範圍內

  • 若程序缺頁率過高,則增加常駐集以分配更多的物理頁面

  • 若程序缺頁率過低,則減少常駐集以減少它的物理頁面數

                        

實現:

  • 訪存時,設定引用位標誌

  • 缺頁時,計算從上次缺頁時間tlast到現在tcurrent的時間間隔
  1. 如果tcurrent– tlast>T,則置換所有在[tlast, tcurrent]時間內沒有被引用的頁

  2. 如果tcurrent – tlast≤ T, 則增加缺失頁到工作集中

                          

該演算法與工作集置換演算法不同點是,頁的調整時間不一樣,前者只是在中斷時進行調整,後者在每一個時間都在調整。這兩個演算法都是工作集大小或缺頁頻率大小動態調整記憶體中需要的頁的情況,區域性演算法只是在滿的時候進行調整。這樣確保經常訪問的頁駐留在記憶體中,應對多個程式時採用全域性頁置換演算法好於區域性頁置換演算法。

抖動問題
  • 如果分配給一個程序的物理頁面太少,不能包含整個工作集,即常駐集屬於工作集,程序會造成很多的缺頁中斷,頻繁在內外存之間替換頁面,使程序的執行慢,這種狀態稱為”抖動”。 
  • 產生抖動的原因:隨著駐留記憶體的程序數目增加,分配給每個程序的物理頁面數不斷減少,缺頁率上升。因此OS要選擇一個適當的程序數目和程序需要的幀數,在併發水平和缺頁率中達到平衡。 

抖動問題可能被本地的頁面置換改善。更好的是載入控制,通過調節併發程序數(MPL)來進行系統負載控制

  • ∑WSt=記憶體的大小

  • 平均缺頁間隔時間(MTBF)=缺頁異常處理時間(PFST)