linux內存管理之內核對物理內存的描述

Linux將物理內存按固定大小的頁面(一般爲4K)劃分內存,在內核初始化時,會建立一個全局struct page結構數組mem_map[ ]。如系統中有76G物理內存,則物理內存頁面數爲76*1024*1024k/4K= 19922944個頁面,mem_map[ ]數組大小19922944,即爲數組中每個元素和物理內存頁面一一對應,整個數組就代表着系統中的全部物理頁面。 在服務器中,存在NUMA架構(如Nehalem、Romly等),Linux將NUMA中內存訪問速度一致(如按照內存通道劃分)的部分稱爲一個節點(Node),用struct pglist_data數據結構表示,通常使用時用它的typedef定義pg_data_t。系統中的每個結點都通過pgdat_list鏈表pg_data_t->node_next連接起來,該鏈接以NULL爲結束標誌。每個結點又進一步分爲許多塊,稱爲區域(zones)。區域表示內存中的一塊範圍。區域用struct zone_struct數據結構表示,它的typedef定義爲zone_t。

每個區域(Zone)中有多個頁面(Pages)組成。節點、區域、頁面三者關係如下圖。

1 節點(Node)

節點(Node),在linux中用struct pglist_data數據結構表示,通常使用時用它的typedef定義pg_data_t,數據結構定義在文件include/linux/mmzone.h中。當分配一個頁面時,linux使用本地結點分配策略,從運行的CPU最近的一個結點分配。 因爲進程傾向於在同一個CPU上運行,使用內存時也就更可能使用本結點的空間。對於象PC之類的UMA系統,僅有一個靜態的pg_data_t結構,變量名爲contig_page_data。遍歷所有節點可以使用for_each_online_pgdat(pgdat)來實現。

2 區域(Zone)

節點(Node)下面可以有多個區域, 共有以下幾種類型:

1)ZONE_DMA
它是低內存的一塊區域,這塊區域由標準工業架構(Industry Standard Architecture)設備使用,適合DMA內存。這部分區域大小和CPU架構有關,在x86架構中,該部分區域大小 限制爲16MB。

2)ZONE_DMA32
該部分區域爲適合支持32位地址總線的DMA內存空間。很顯然,該部分僅在64位系統有效,在32位系統中,這部分區域爲空。在x86-64架構中,這部分的區域範圍爲0~4GB。

3)ZONE_NORMAL
屬於ZONE_NORMAL的內存被內核直接映射到線性地址。這部分區域僅表示可能存在這部分區域,如在64位系統中,若系統只有4GB物理內存,則所有的物理內存都屬於 ZONE_DMA32,而ZONE_NORMAL區域爲空。許多內核操作都僅在ZONE_NORMAL內存區域進行,所以這部分是系統性能關鍵的地 方。

4)ZONE_HIGHMEM
是系統中剩下的可用內存,但因爲內核的地址空間有限,這部分內存不直接映射到內核。

在x86架構中內存有三種區域:ZONE_DMA,ONE_NORMAL,ZONE_HIGHMEM,不同類型的區域適合不同需要。在32位系統中結構中,1G(內核空間)/3G(用戶空間) 地址空間劃分時,三種類型的區域如下:
ZONE_DMA              內存開始的16MB
ZONE_NORMAL       16MB~896MB
ZONE_HIGHMEM     896MB ~ 結束

4G(內核空間)/4G(用戶空間)地址空間劃分時,三種類型區域劃分爲:
ZONE_DMA              內存開始的16MB
ZONE_NORMAL       16MB~3968MB
ZONE_HIGHMEM     3968MB ~ 結束

在64位Linux系統中,內存只有三個區域DMA、DMA32和NORMAL。
ZONE_DMA              內存開始的16MB
ZONE_DMA32          16MB~4GB
ZONE_NORMAL       4GB ~ 結束

下圖是32位系統和64位系統對應的內存區域劃分:

3 頁面(Page)

系統內存由固定的塊組成,稱爲頁幀,每個頁幀由struct page結構描述。內核在初始化時,會根據內存的大小計算出由多少頁幀,每個頁幀都會有一個page結構與之對應,這些 信息保存在全局數組變量mem_map中。mem_map通常存儲在ZONE_NORMAL區域中, 在內存較小的機器中,會保存在加載內核鏡像後的一片保留空間裏。有多少個物理頁面,就會有多個struct page結構,如系統安裝128GB物理內存,struct page結構體大小爲40字節,則mem_map[ ]數組就佔用物理內存大小爲128*1024*1024k/4k * 40 = 1280MB,即Linux內核要使用1280MB物理內存來保存mem_map[ ]數組,這部分內存是不可被使用的,因此 struct page結構體大小不能設計很大。

頁面標誌尤爲重要,在內存分配與回收、I/O操作等重要內核活動過程中都會使用到頁面標誌。所有的標誌在include/linux/page-flags.h中定義。下面解釋一下重要的幾個頁面標誌:
PG_locked:頁面是否被鎖住,若該位設置了該位,則不允許內核其他部分訪問該頁面。這用來防止內存管理過程中遇到的競爭條件,如當從硬盤讀取數據到一個頁面時,就不允許其他內核部分訪問該頁面,因爲讀數據的過程中,其他內核部分能訪問的話,則讀取到的數據是不完整的。
PG_error:I/O出錯,且操作和頁面有關,就設置該標誌。
PG_referenced和PG_active:控制系統使用頁面的活躍程度,這個信息對swap系統選擇待交換出的頁面非常重要。
PG_update:表示成功完成從塊設備上讀取一個頁面的數據。該標誌和塊設備I/O操作有關。
PG_dirty:當內存頁面中的數據和塊設備上的數據不一致時,就設置該標誌。在寫數據到塊設備時,爲了提高將來的讀性能,數據並不是立即回寫到塊設備上,而只是設置頁面髒 標誌,表示該頁面數據需要回寫。
PG_lru:該標誌用來實現頁面回收和交換。
PG_highmem:表示該頁面爲屬於高端內存。

發佈了80 篇原創文章 · 獲贊 60 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章