LRU演算法的實現

2021-09-30 09:36:24 字數 2312 閱讀 4226

什麼是lru演算法? lru是least recently used的縮寫,即最近最少使用頁面置換演算法,是為虛擬頁式儲存管理服務的。

關於作業系統的記憶體管理,如何節省利用容量不大的記憶體為最多的程序提供資源,一直是研究的重要方向。而記憶體的虛擬儲存管理,是現在最通用,最成功的方式——在記憶體有限的情況下,擴充套件一部分外存作為虛擬記憶體,真正的記憶體只儲存當前執行時所用得到資訊。這無疑極大地擴充了記憶體的功能,極大地提高了計算機的併發度。虛擬頁式儲存管理,則是將程序所需空間劃分為多個頁面,記憶體中只存放當前所需頁面,其餘頁面放入外存的管理方式。

然而,有利就有弊,虛擬頁式儲存管理減少了程序所需的記憶體空間,卻也帶來了執行時間變長這一缺點:程序執行過程中,不可避免地要把在外存中存放的一些資訊和記憶體中已有的進行交換,由於外存的低速,這一步驟所花費的時間不可忽略。因而,採取盡量好的演算法以減少讀取外存的次數,也是相當有意義的事情。

對於虛擬頁式儲存,內外存資訊的替換是以頁面為單位進行的——當需要乙個放在外存的頁面時,把它調入記憶體,同時為了保持原有空間的大小,還要把乙個記憶體中頁面調出至外存。自然,這種調動越少,程序執行的效率也就越高。那麼,把哪個頁面調出去可以達到調動盡量少的目的?我們需要乙個演算法。

自然,達到這樣一種情形的演算法是最理想的了——每次調換出的頁面是所有記憶體頁面中最遲將被使用的——這可以最大限度的推遲頁面調換,這種演算法,被稱為理想頁面置換演算法。可惜的是,這種演算法是無法實現的。

為了儘量減少與理想演算法的差距,產生了各種精妙的演算法,最近最少使用頁面置換演算法便是其中乙個。lru演算法的提出,是基於這樣乙個事實:在前面幾條指令中使用頻繁的頁面很可能在後面的幾條指令中頻繁使用。反過來說,已經很久沒有使用的頁面很可能在未來較長的一段時間內不會被用到。這個,就是著名的區域性性原理——比記憶體速度還要快的cache,也是基於同樣的原理執行的。因此,我們只需要在每次調換時,找到最近最少使用的那個頁面調出記憶體。這就是lru演算法的全部內容。

如何用具體的資料結構來實現這個演算法?

首先,最容易想到,也最簡單的方法:計時法。給頁表中的每一頁增加乙個域,專門用來存放計時標誌,用來記錄該頁面自上次被訪問以來所經歷的時間。頁面每被訪問一次,計時清0。要裝入新頁時,從記憶體的頁面中選出時間最長的一頁,調出,同時把各頁的計時標誌全部清0,重新開始計時。

計時法可以稍作改變,成為計數法:頁面被訪問,計數標誌清0,其餘所有記憶體頁面計數器加1;要裝入新頁時,選出計數最大的一頁調出,同時所有計數器清0。

這兩種方法確實很簡單,但執行效率卻不盡如人意。每個時刻,或是每呼叫乙個頁面,就需要對記憶體中所有頁面的訪問情況進行記錄和更新,麻煩且開銷相當大。

另一種實現的方法:鍊錶法。

作業系統為每個程序維護一條鍊錶,鍊錶的每個結點記錄一張頁面的位址。呼叫一次頁面,則把該頁面的結點從鏈中取出,放到鏈尾;要裝入新頁,則把鏈頭的頁面調出,同時生成調入頁面的結點,放到鏈尾。

鍊錶法可看作簡單計時/計數法的改良,維護乙個鍊錶,自然要比維護所有頁面標誌要簡單和輕鬆。可是,這並沒有在數量級上改變演算法的時間複雜度,每呼叫乙個頁面,都要在鍊錶中搜尋對應結點並放至鏈尾的工作量並不算小。

以上是單純使用軟體實現的演算法。不過,如果能有特殊的硬體幫忙,我們可以有更有效率的演算法。

首先,如果硬體有乙個64位的計數器,每條指令執行完後自動加1。在每個頁表項裡新增乙個域,用於存放計數器的值。程序執行,每次訪問頁面的時候,都把計數器的值儲存在被訪問頁面的頁表項中。一旦發生缺頁,作業系統檢查頁表中所有的計數器的值以找出最小的乙個,那這一頁就是最久未使用的頁面,調出即可。

其次,另外乙個矩陣演算法:在乙個有n個頁框的機器中,lru硬體可以維持乙個n*n的矩陣,開始時所有位都是0。訪問到第k頁時,硬體把k行的位全設為1,之後再把k列的位置設為0。容易證明,在任意時候,二進位制值最小的行即為最久未使用的頁面,當調換頁面時,將其調出。

以上的兩種演算法,無疑都要比純粹的軟體演算法方便且快捷。每次頁面訪問之後的操作——儲存計數器值和設定k行k列的值,時間複雜度都是o(1)量級,與純軟體演算法不可同日而語。

那是否軟體演算法就毫無用處?當然不是,硬體演算法有它致命的缺陷,那就是需要硬體的支援才能執行。如果機器上恰好有所需硬體,那無疑是再好不過;反之,若機器上沒有這種硬體條件,我們也只能無奈地拋棄硬體演算法,轉而選取相對麻煩的軟體演算法了。

最後,讓我們來談論一下lru演算法。首先,這是乙個相當好的演算法,它是理想演算法很好的近似。在計算機系統中應用廣泛的區域性性原理給它打造了堅實的理論基礎,而在實際運用中,這一演算法也被證明擁有極高的效能。在大規模的程式執行中,它產生的缺頁中斷次數已很接近理想演算法。或許我們還能找到更好的演算法,但我想,得到的收益與付出的代價恐怕就不成比例了。當然,lru演算法的缺點在於實現方法的不足——效率高的硬體演算法通常在大多數機器上無法執行,而軟體演算法明顯有太多的開銷。與之相對的,fifo演算法,和與lru相似的nru演算法,效能儘管不是最好,卻更容易實現。所以,找到乙個優秀的演算法來實現lru,就是乙個非常有意義的問題。

LRU演算法的實現

0 推薦 lru演算法的實現 什麼是lru演算法lru是least recently used的縮寫,即最近最少使用頁面置換演算法,是為虛擬頁式儲存管理服務的.關於作業系統的記憶體管理,如何節省利用容量不大的記憶體為最多的程序提供資源,一直是研究的重要方向.而記憶體的虛擬儲存管理,是現在最通用,最成...

LRU演算法的實現

什麼是lru演算法?lru是least recently used的縮寫,即最近最少使用頁面置換演算法,是為虛擬頁式儲存管理服務的。關於作業系統的記憶體管理,如何節省利用容量不大的記憶體為最多的程序提供資源,一直是研究的重要方向。而記憶體的虛擬儲存管理,是現在最通用,最成功的方式 在記憶體有限的情況...

LRU演算法實現

jdk 中的實現 在jdk 中linkedhashmap 可以作為lru 演算法以及插入順序的實現,linkedhashmap 繼承自hashmap 底層結合hash 表和雙向鍊錶,元素的插入和查詢等操作通過計算hash 值找到其陣列位置,在做插入或則查詢操作是,將元素插入到鍊錶的表頭 當然得先刪除...