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/