linux核心使用了lru算法來置換記憶體頁面,但是實際上并不是純的lru算法,裡面摻雜了很多别的思想,比如第二次機會,比如雙時鐘指針等等。這裡着重說一下第二次機會的展現。在核心中有一個mark_page_accessed函數,它實際上展現一個狀态機,這是它的實作:
if (!PageActive(page) && PageReferenced(page) && PageLRU(page)) {
activate_page(page);
ClearPageReferenced(page);
} else if (!PageReferenced(page)) {
SetPageReferenced(page);
}
基本上這段代碼展現了函數注釋中的言詞:
inactive,unreferenced -> inactive,referenced
inactive,referenced -> active,unreferenced
active,unreferenced -> active,referenced
一個被記憶體管理系統管理的page的生命周期就是:夥伴系統->active list->inactive list->夥伴系統。
當一個page在兩個list之間晃蕩的時候,并不是一次性從active轉移到inactive或者相反的移動,而是有兩次機會,inactive的page要先referenced才能進一步變成active的,同樣的active的page要先清除了referenced才能變成inactive的,上面的函數是到active的變換,下面的page_referenced其實是到inactive的變換,每當置換算法掃描到一個頁面的時候,就要老化它一次,這裡有一個技巧,那就是不管它是active的還是inactive的,隻是清除一下referenced,隻要它被referenced了,那麼它就理應不該被釋放,除非它既是inactive的又是unreferenced的:
int page_referenced(struct page *page, int is_locked)
{
int referenced = 0;
if (page_test_and_clear_young(page))
referenced++;
if (TestClearPageReferenced(page))
if (page_mapped(page) && page->mapping) {
...//檢查page是否剛被使用
}
return referenced;
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1271157