概況
以前實現作業系統通常把記憶體劃分得很明確,例如記憶體通常包括Cache和Buffer以及自由記憶體(Free) 等等,角色明確。現代作業系統則在記憶體管理上不再那樣分明,通常整個物理記憶體都當作Cache來用。
詳解
作業系統中物理記憶體通常是分頁管理的,而且由體系結構決定頁面大小,例如在Intel i386類型的 CPU上,物理記憶體頁的大小是4096位元組。FreeBSD的虛擬記憶體稱為一種unified Buffer Cache的技術,字面意義就是cache和buffer是統一管理的。為了支持分頁交換,每個進程的地址空間都有一個叫做vm_map 的連結表來管理,而且每個地址範圍內的一項通常有一個叫做vm_object_t的類型來為程式需要某個頁面時提供申請一個新頁面後從某處載入保存的數據到該新頁上,同時該新頁被映射進進程的虛擬地址空間,每個頁面的控制信息由一個叫做vm_page_t的結構類表示,一個頁面某一個時刻只能歸一個vm_object_t擁有,vm_object_t代表了記憶體與外部數據源之間的聯繫,當頁面從硬碟換入時,它為頁面提供數據,當頁面需要拿作他用,vm_object_t又會把數據保存到硬碟某個地方。vm_object_t可以使用各種數據源,不一定是硬碟交換區,還可以是一個磁碟檔案,也可以是一塊顯示卡中的記憶體區。
頁面列隊
為了反映系統動態地使用物理記憶體,FreeBSD在核心中建立一些頁面佇列,其中主要有active, inactive, cache, 和free四種佇列。
active是當前系統中在一定的時間內被持續使用的頁面,系統中有一個後台核心進程專門掃描active佇列,當有發現好久沒有使用某個頁面時,核心就會把該頁面移動到inactive佇列。
cache佇列中的頁面是有些子系統釋放某些頁面,但是頁面中的數據依然有效,將來還有可能再次使用其中的數據的頁面,只是這些頁面已經是“乾淨的”,不用再存檔,典型的是檔案系統使用這種技術,用戶關閉檔案,但是檔案系統有自己的cache管理,不一定就立即關閉檔案,而將數據留在記憶體中,以便下次使用時能迅速獲得數據而不需要讀盤。
free的意思很明了,其中不包含數據也沒有誰再與其有聯繫。無論上述是哪種頁面,核心都可以隨時那來作其他用途,只是使用的優先權別不一樣,在核心需要一個新頁時,free的頁面被最先考慮,但是當數值小於一定量時,就會從cache類型的佇列中找,cache中的頁面被取出時,需要與原來的vm_object互動,或許要脫鉤,當然沒有申請free的頁面來得快,但使用cache還是很快的,如果cache佇列中沒有了頁面,就會去找inactive佇列中的頁面, inactive中的頁面有可能是“Dirty”,在拿做其他用途時,不但要與原來的vm_object脫鉤,而且還要因為是“Dirty”而要引起寫盤,萬不得已時active佇列中的頁面就會被拿作他用,這是系統會非常繁忙了。
以上佇列的實現是使用LRU算法。為了最佳化使用CPU的L2 cache,避免給同一個vm_object_t(通常代表一個數據實體)分配映射到同一個L2 cache 行上的頁面,cache和free佇列都有通常有好幾個佇列,分配是根據一定的算法輪流在這些佇列上獲取頁面,這個機製成為page coloring。
系統中還有另外一類頁面,叫做wired, 意思是被掛起的,這些頁面是不在上面講的佇列中的,因此它不能被交換到硬碟,這些頁面多了會導致系統使用記憶體緊張,需要交換時可以活動的餘地就會減少,導致系統性能下降。通常核心中的數據結構都使用wired頁面,避免在核心使用自己的數據時發生缺頁而導致不可預料的結果,通常是無法恢復故障而崩潰,負載較重的系統,wired頁面會多一些。而除了核心使用的記憶體是wired以外,用戶進程則幾 乎全部使用上述四種佇列種的頁面,全是可以被丟棄而再重新恢復的那種類型。wired頁面還可以由用戶進程調用mlock系統調用鎖定頁面而引起的。
小結
FreeBSD的虛擬記憶體是與檔案系統和其他數據源渾然連成一體的,整個記憶體被視做一個巨大的cache, 充分加以利用,平常見到一個系統讀過硬碟上很多檔案或讀過一個巨大無比的檔案,系統的cache類型的頁面就會很多,而free減少就是上邊講的機制所產生的現象,這是一種優勢,使得系統整體性能得到極大提高。