歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Personal Notes on Linux Virtual Memory Management

前幾天簡單翻了遍《Understanding Linux Kernel Memory Management》,正文很短,讀起來並不容易,該屬於常讀常新的書了。趁印象還熱乎先記一點筆記吧,內容比較個人化沒有什麼條理,見諒了 :p

『內存管理』其實是個很寬泛的詞,物理頁管理、頁表管理、地址空間管理、內存分配等等,單獨拿出每一塊出來都可以稱作『內存管理』,但其間差異何其巨大,用一個詞蓋過去,就像是一葉障目,不見樹林。要理解它的全貌,還是要分開討論比較好。如果能將每個局部都搞清楚的話,總不至於見不到全局的。

系統初始化與內存布局

在引導階段(setup.o),內核會先映射兩個臨時頁表到頁目錄swapper_pg_dir^1 的前兩項,將0~8m, 3g~3g+8m的虛擬地址同時映射到0~8m的物理地址。

內核頁表的初始化則是在內核初始化階段的kernel_physical_mapping_init()函數中。如果可以,就利用PSE設置大頁;利用PGE設置全局頁,將內存映射固定在TLB中,在切換地址空間時不需要重新刷新。

Linux固定映射內核地址空間。在x86的機器上,物理內存分為3個Zone:
◦ZONE_DMA: 0~16m
◦ZONE_NORMAL: 16m~896m
◦ZONE_HIGHMEM: 896m~

其中ZONE_DMA與ZONE_NORMAL都是固定映射到0xc000000處,剩余128mb的地址空間用於映射ZONE_HIGHMEM中的物理頁,抑或FIXMAP。

在x64中,地址空間已足夠映射所有的物理內存,ZONE_HIGHMEM為空。

kmap

要在內核中使用ZONE_HIGHMEM中的內存,必先通過kmap()將它映射到內核地址空間。

但kmap()有可能進入睡眠,在中斷上下文中必須使用kmap_atomic()。

Buddy Allocator與物理頁面管理

在linux中,Buddy Allocator就是作為頁級內存分配器了,用於分配2次冪大小的連續物理頁面。它同時作為內核內存分配器與Page Cache的後端。

相關的例程為alloc_pages(gfp_t gfp_mask, unsigned int order),它將返回一只page結構組成的鏈表。

資源有限怎麼辦
◦bounce buffer: DMA內存有限,空間換生存周期;
◦kmap_atomic(): 預留的頁表項有限,盡快的用,盡快的釋放。

NUMA與Node

在SMP系統上,當CPU增多時,無差別的內存訪問成為了影響伸縮性的一項瓶頸^2 。為此的解決方案是為每塊處理器單獨提供一塊連續的內存,原則上處理器盡可能只訪問靠近自己的內存,從而提高內存訪問的伸縮。這就是NUMA(Non-Uniform Memory Access,非一致內存訪問),其中的每塊處理器與內存被合稱為Node。

而內核需要做的,就是在CPU分配內存時盡量只分配本Node中的內存。在Linux中,表示Node的結構為pg_data_t。

Slab與內核內存分配

內核中要使用內存,就用Slab了。它將buddy allocator作為後端,申請來大塊的內存分成小塊,每個slab中都是等大的內存塊。
◦kmem_cache_alloc()與kmem_cache_free(),專用內存分配器,用於分配內核中常用的結構。
◦kmalloc()與kfree(),通用內存分配器。它的背後是一組不同大小的slab。

如果結構的分配/釋放不是特別頻繁,一般只用kmalloc()就足夠了。

頁表管理

x86的linux的三級頁表其實是為PAE准備的,64位機器的話,得有四級才行。

misc notes
◦struct address_space這個名字有一定誤導性,實際上內核中描述用戶地址空間的結構為struct mm_struct。struct address_space這個結構更像是用來描述Page Cache的。
◦GFP為Get Free Page的縮寫。

Copyright © Linux教程網 All Rights Reserved