1. 程式人生 > >記憶體的頁面置換演算法

記憶體的頁面置換演算法

請求分頁系統建立在基本分頁系統基礎之上,為了支援虛擬儲存器功能而增加了請求調頁功能和頁面置換功能。請求分頁是目前最常用的一種實現虛擬儲存器的方法。

在請求分頁系統中,只要求將當前需要的一部分頁面裝入記憶體,以便可以啟動作業執行。在作業執行過程中,當所要訪問的頁面不在記憶體時,再通過雕爺功能將其調入,同時還可以通過置換功能將暫時不用的頁面換出到外存上,以便騰出記憶體空間。

頁面置換演算法的主要目標是使頁面置換頻率最低(也可以說缺頁率最低)。

常見的頁面置換演算法有以下幾種:

1、最佳置換演算法(Optimal,OPT)

所選擇的被換出的頁面將是以後永不使用的,或者是在最長時間內不再被訪問,通常可以保證獲得最低的缺頁率。但是由於人們無法預知一個頁面多長時間不再被訪問,因此該演算法是一種理論上的演算法。最佳置換演算法可以用來評價其他演算法。

舉例:一個系統為某程序分配了三個物理塊,並有如下頁面引用序列:

開始執行時,先將 7, 0, 1 三個頁面裝入記憶體。當程序要訪問頁面 2 時,產生缺頁中斷,根據最佳置換演算法,頁面 7 在第18次訪問才需要調入,再次被訪問的時間最長,因此會將頁面 7 換出,後面的過程以此類推,具體過程如下圖;

2、先進先出頁面置換演算法(First In First Out,FIFO)

選擇換出的頁面是最先進入的頁面。該演算法實現簡單,但會將那些經常被訪問的頁面也被換出,從而使缺頁率升高。

舉例:仍使用上面的例子,使用FIFO演算法進行頁面置換,過程如下:

進行了12次頁面置換,比最佳置換演算法正好多一倍。

FIFO演算法還會產生 當分配的物理塊數增大而頁故障數不減反增的異常現象,稱為Belady異常。FIFO演算法可能出現Belady異常,而LRU和OPT演算法永遠不會。

3、最近最久未使用( Least Recently Used,LRU)置換演算法

雖然無法知道將來要使用的頁面情況,但是可以知道過去使用頁面的情況。LRU 將最近最久未使用的頁面換出,它認為過去一段時間內未使用的頁面,在最近的將來也不會被訪問。

實現方式一:

在記憶體中維護一個所有頁面的連結串列。當一個頁面被訪問時,將這個頁面移到連結串列表頭。這樣就能保證連結串列表尾的頁面時最近最久未訪問的。

實現方式二:

為每個頁面設定一個訪問欄位,來記錄頁面自上次被訪問以來所經歷的時間,淘汰頁面時選擇現有頁面中值最大的予以淘汰。

使用和上面同樣的例項,採用LRU演算法進行頁面置換:

LRU效能較好,但需要暫存器和棧的硬體支援,LRU是堆疊類的演算法,理論上可以證明,堆疊類演算法不可能出現Belady異常,FIFO演算法基於佇列實現,不是堆疊類演算法。

4、第二次機會演算法

FIFO 演算法可能會把經常使用的頁面置換出去,為了避免這一問題,對該演算法做一個簡單的修改:

當頁面被訪問 (讀或寫) 時設定該頁面的 R 位為 1。需要替換的時候,檢查最老頁面的 R 位。如果 R 位是 0,那麼這個頁面既老又沒有被使用,可以立刻置換掉;如果是 1,就將 R 位清 0,並把該頁面放到連結串列的尾端,修改它的裝入時間使它就像剛裝入的一樣,然後繼續從連結串列的頭部開始搜尋。

5、時鐘演算法(clock)

第二次機會演算法需要在連結串列中移動頁面,降低了效率。時鐘演算法使用環形連結串列將頁面連結起來,再使用一個指標指向最老的頁面。

最簡單的時鐘策略需要給每一頁框關聯一個附加位,稱為使用位。當某一頁首次裝入記憶體中時,則將該頁頁框的使用位設定為1;當該頁隨後被訪問到時(在訪問產生缺頁中斷之後),它的使用位也會被設定為1。該方法中,用於置換的候選頁框集合(當前程序:區域性範圍;整個記憶體;全域性範圍)被看做是一個迴圈緩衝區,並且有一個指標針與之相關聯。當一頁被置換時,該指標針被設定成指向緩衝區中的下一頁框。當需要置換一頁時,作業系統掃描緩衝區,以查詢使用位被置為0的一頁框。每當遇到一個使用位為1的頁框時,作業系統就將該位重新置為0;如果在這個過程開始時,緩衝區中所有頁框的使用位均為0時,則選擇遇到的第一個頁框置換;如果所有頁框的使用位均為1時,則指標針在緩衝區中完整地迴圈一週,把所有使用位都置為0,並且停留在最初的位置上,置換該頁框中的頁當需要使用的頁已經存在時,則指標不會受到影響,不會發生轉動。

可見該策略類似於FIFO(先進先出),唯一不同的是,在時鐘策略中使用位為1的頁框被跳過,該策略之所以稱為時鐘策略,是因為可以把頁框形象地想象成在一個環中。許多作業系統都採用這種簡單時鐘策略的某種變體。

以下是一個使用例項,其中*號表示相應的使用位為1,紅色單元格表示指標指向的位置

6、改進時鐘演算法

在頁面中增加了修改位,1為修改過,0為未修改過。因為當發生缺頁中斷時,把未修改過的頁面替換進外存就相當於把頁面直接從記憶體中刪除,因為記憶體和外存中所對應的該頁面的內容相同,處理時間只有一次缺頁中斷訪問外存的時間。而修改過的頁面則還需要向外存中寫入一次,再加上缺頁中斷的時間,相當於訪問了兩次外存,是上述未修改的兩倍。所以避免把修改過的頁面替換下去可以提高效能。

由訪問位A和修改位M可以組合成下面四種類型的頁面: 

  • 1類(A=0, M=0): 表示該頁最近既未被訪問, 又未被修改, 是最佳淘汰頁。 
  • 2類(A=0, M=1): 表示該頁最近未被訪問, 但已被修改, 並不是很好的淘汰頁。 
  • 3類(A=1, M=0): 最近已被訪問, 但未被修改, 該頁有可能再被訪問。 
  • 4類(A=1, M=1): 最近已被訪問且被修改, 該頁可能再被訪問。

可能有人會發現第2類這種情況根本不會出現,如果一個頁幀被修改,其修改位會被置1,同時它也被使用了,其使用位也會被置1;即不會出現被修改但是沒有被使用的情況。真實情況是,頁幀的使用位可能會被清零,這樣第3組經過一次清零就會變成第2組。

演算法執行如下操作步驟:

  1. 從指標的當前位置開始,掃描幀緩衝區。在這次掃描過程中,對使用位不做任何修改。選擇遇到的第一類頁(A=0,M=0)作為淘汰頁。
  2. 如果第1)步失敗,則開始第二輪掃描,查詢(A=0,M=1)的第二類頁。選擇遇到的第一個這樣的頁作為淘汰頁。在這個掃描過程中,對所有經過的頁,把它的訪問位A設定成0。
  3. 如果第2)步失敗,指標將回到它的最初位置,並且集合中所有頁的訪問位均為0。重複第1步,並且如果有必要,重複第2步。這樣將可以找到被淘汰的頁。

改進型的CLOCK演算法優於簡單CLOCK演算法之處在於替換時首選沒有變化的頁。由於修改過的頁在被替換之前必須寫回,因而這樣做會節省時間。

7、最不常用演算法(LFU,Least Frequently Used)

是基於“如果一個數據在最近一段時間內使用次數很少,那麼在將來一段時間內被使用的可能性也很小”的思路。

這種演算法選擇最近時期使用次數最少的頁作為淘汰頁。為每個頁面配置一個計數器,一旦某頁被訪問,則將其計數器的值加1,在需要選擇一頁置換時,則將選擇其計數器值最小的頁面,即記憶體中訪問次數最少的頁面進行淘汰。

這種演算法可能存在的問題是:有些也在程序開始時被訪問的次數很多,但以後這些頁可能不再被訪問,這樣的頁不該長時間停留在記憶體中。解決這個問題的方法之一是定期的將計時器右移,以形成指數衰減的平均使用次數。

注意LFU和LRU演算法的不同之處,LRU的淘汰規則是基於訪問時間,而LFU是基於訪問次數的。

抖動