linux記憶體管理的兩個主要特徵是進程虛擬記憶體和核心記憶體配置。
先來談談進程虛擬記憶體是什麼,linux使用三級頁表結構,由頁目錄,頁中間目錄,頁表構成。
頁目錄:一個活動的進程有一個頁目錄,頁目錄大小為一頁尺寸,頁目錄中的每一項都指向頁中間目錄的一頁。
頁中間目錄:頁中間目錄可以有多個頁,頁中間目錄的每一項指向頁表中的一頁。
頁表:頁表也可以有多頁,每個頁表項指向該進程的一個虛擬頁。
虛擬記憶體方案的地址轉換如下:
為了提高讀寫記憶體的效率,linux把連續的頁映射到連續的葉框中,基於這種目的,linux使用了夥伴系統核心維護一系列固定大小的葉框組一頁可以包含1、2、4、8、16、32個葉框,當一頁在記憶體中分配或者回收時,可用的組使用夥伴演算法被分裂或合并。
linux的頁面置換演算法是時鐘演算法的變種。
核心記憶體配置是什麼,核心記憶體管理實體記憶體頁框,主要是為特定的使用分配和回收頁框,而頁框的擁有者可能是使用者空間的進程,動態分配的核心資料,靜態核心代碼和快取等,linux的核心記憶體配置使用的是基於使用者虛擬記憶體管理的分頁機制,在分頁機制中使用夥伴演算法可以以一頁或者多頁為單位分配,所以這種分配的單位最小是頁,而核心中有許多小對象,這些對象的構建和回收十分頻繁,如inode,如果每次構件時就向核心申請一個頁,而其實實際大小可能只有幾個位元組,這樣就非常浪費,所以linux在分配頁時採用了一種slab機制,一般的頁尺寸為4K,而slab就是用來處理在同一頁框中分配小儲存區,小於一頁的塊可以非配給32、64、128、256...4048位元組,linux維護了一組緩衝鏈表,每種塊大小對應一個鏈表,塊可以按照類似夥伴演算法的方式進行合并,並且可以在鏈表間移動。
slab層主要起到了兩個方面的作用:
1. slab可以對小對象進行分配,這樣就不用為每個小對象分配一個頁框,節省了空間。
2. 核心中的一些小對象建立析構很頻繁,slab對這些小對象做了緩衝,可以重複利用一些相同的對象,減少記憶體配置次數。
slab結構如下:
linux是通過快取來管理相同大小的塊或者說對象吧。每個緩衝都包含了一組slab列表,主要有三種不同類型的slab組成的鏈表:
slab_full:完全分配了,沒有閒置列表
slab_partial:分配了部分塊的列表
slab_free:完全閒置slab
當請求記憶體時會先從slab_partial中尋找,如果沒有就會去slab_free中去尋找,然後將這個slab放入slab_partial中。
與傳統的記憶體管理員模式相比, slab 緩衝分配器提供了很多優點。首先,核心通常依賴於對小對象的分配,它們會在系統生命週期內進行無數次分配。slab 緩衝分配器通過對類似大小的對象進行緩衝而提供這種功能,從而避免了常見的片段問題。slab 分配器還支援通用對象的初始化,從而避免了為同一目而對一個對象重複進行初始化。最後,slab 分配器還可以支援硬體緩衝對齊和著色,這允許不同緩衝中的對象佔用相同的緩衝行,從而提高緩衝的利用率並獲得更好的效能。
參考連結:https://www.ibm.com/developerworks/cn/linux/l-linux-slab-allocator/