linux 內存管理3

這篇是對第一篇內存管理的最好的補充。

 

在支持MMU32位處理器平臺上,Linux系統中的物理存儲空間和虛擬存儲空間的地址範圍分別都是從0x000000000xFFFFFFFF,共4GB,但物理存儲空間與虛擬存儲空間佈局完全不同。Linux運行在虛擬存儲空間並負責把系統中實際存在的遠小於4GB的物理內存根據不同需求映射到整個4GB的虛擬存儲空間中

 

物理存儲空間佈局

Linux的物理存儲空間佈局與處理器相關,詳細情況可以從處理器用戶手冊的存儲空間分佈表(memory map)相關章節中查到,我們這裏只列出嵌入式處理器平臺Linux物理內存空間的一般佈局,如圖18-4所示。

 

 

說明:

1)最大noden不能大於MAX_NUMNODES-1

 

2MAX_NUMNODES表示系統支持的最多node數。在ARM系統中,Sharp芯片最多支持16nodes,其他芯片最多支持4nodes

 

3numnodes是當前系統中實際的內存node數。

 

4)在不支持CONFIG_DISCONTIGMEM選項的系統中,只有一個內存node

 

5)最大bankm不能大於NR_BANKS-1

 

6NR_BANKS表示系統中支持的最大內存bank數,一般等於處理器的RAM片選數。在ARM系統中,Sharp芯片最多支持16banks,其他芯片最多支持8banks

 

7mem_init()函數會將所有節點的頁幀位碼錶所佔空間、孔洞頁描述符空間及空閒內存頁都釋放掉。

 

好像不是很明白。

 

虛擬存儲空間佈局

在支持MMU的系統中,當系統做完硬件初始化後就使能MMU功能,這樣整個系統就運行在虛擬存儲空間中,實現虛擬存儲空間到物理存儲空間映射功能的是處理器的MMU,而虛擬存儲空間與5路存儲空間的映射關係則是由Linux內核來管理的。32位系統中物理存儲空間佔4GB空間,虛擬存儲空間同樣佔4GB空間,Linux把物理空間中實際存在的遠遠小於4GB的內存空間映射到整個4GB虛擬存儲空間中除映射I/O空間之外的全部空間,所以虛擬內存空間遠遠大於物理內存空間,這就說同一塊物理內存可能映射到多處虛擬內存地址空間上,這正是Linux內存管理職責所在。圖18-5列出了Linux內核中虛擬內存空間的一般佈局(其實I/O空間也在其中,通常佔用高端內存空間,在此未標出)。

 

 

說明:

 

1)線性地址空間:是指Linux系統中從0x000000000xFFFFFFFF整個4GB虛擬存儲空間。

 

2)內核空間:內核空間表示運行在處理器最高級別的超級用戶模式(supervisor mode)下的代碼或數據,內核空間佔用從0xC00000000xFFFFFFFF1GB線性地址空間,內核線性地址空間由所有進程共享,但只有運行在內核態的進程才能訪問,用戶進程可以通過系統調用切換到內核態訪問內核空間,進程運行在內核態時所產生的地址都屬於內核空間。

 

3)用戶空間:用戶空間佔用從0x000000000xBFFFFFFF3GB的線性地址空間,每個進程都有一個獨立的3GB用戶空間,所以用戶空間由每個進程獨有,但是內核線程沒有用戶空間,因爲它不產生用戶空間地址。另外子進程共享(繼承)父進程的用戶空間只是使用與父進程相同的用戶線性地址到物理內存地址的映射關係,而不是共享父進程用戶空間。運行在用戶態和內核態的進程都可以訪問用戶空間。

 

4)內核邏輯地址空間:是指從PAGE_OFFSET(3G)high_memory(物理內存的大小,最大896)之間的線性地址空間,是系統物理內存映射區,它映射了全部或部分(如果系統包含高端內存)物理內存。內核邏輯地址空間與圖18-4中的系統RAM內存物理地址空間是一一對應的(包括內存孔洞也是一一對應的),內核邏輯地址空間中的地址與RAM內存物理地址空間中對應的地址只差一個固定偏移量(3G),如果RAM內存物理地址空間從0x00000000地址編址,那麼這個偏移量就是PAGE_OFFSET

 

5)低端內存:內核邏輯地址空間所映射物理內存就是低端內存(實際物理內存的大小,但是小於896),低端內存在Linux線性地址空間中始終有永久的一一對應的內核邏輯地址,系統初始化過程中將低端內存永久映射到了內核邏輯地址空間爲低端內存建立了虛擬映射頁表。低端內存內物理內存的物理地址與線性地址之間的轉換可以通過__pa(x)__va(x)兩個宏來進行,#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) __pa(x)將內核邏輯地址空間的地址x轉換成對應的物理地址,相當於__virt_to_phys((unsigned long)(x))__va(x)則相反,把低端物理內存空間的地址轉換成對應的內核邏輯地址,相當於((void *)__phys_to_virt((unsigned long)(x)))

 

6)高端內存:低端內存地址之上的物理內存是高端內存(物理內存896之上),高端內存在Linux線性地址空間中沒有固定的一一對應的內核邏輯地址,系統初始化過程中不會爲這些內存建立映射頁表將其固定映射到Linux線性地址空間,而是需要使用高端內存的時候才爲分配的高端物理內存建立映射頁表,使其能夠被內核使用,否則不能被使用。高端內存的物理地址於線性地址之間的轉換不能使用上面的__pa(x)__va(x)宏。

 

7)高端內存概念的由來:如上所述,Linux4GB的線性地址空間劃分成兩部分,0x000000000xBFFFFFFF3GB空間作爲用戶空間由用戶進程獨佔,這部分線性地址空間並沒有固定映射到物理內存空間上;從0xC00000000xFFFFFFFF的第4GB線性地址空間作爲內核空間,在嵌入式系統中,這部分線性地址空間除了映射物理內存空間之外還要映射處理器內部外設寄存器空間等I/O空間。0xC0000000~high_memory之間的內核邏輯地址空間專用來固定映射系統中的物理內存,也就是說0xC0000000~high_memory之間空間大小與系統的物理內存空間大小是相同的(當然在配置了CONFIG_DISCONTIGMEMD選項的非連續內存系統中,內核邏輯地址空間和物理內存空間一樣可能存在內存孔洞),如果系統中的物理內存容量遠小於1GB,那麼內核線性地址空間中內核邏輯地址空間之上的high_memory~0xFFFFFFFF之間還有足夠的空間來固定映射一些I/O空間。可是,如果系統中的物理內存容量(包括內存孔洞)大於1GB,那麼就沒有足夠的內核線性地址空間來固定映射系統全部物理內存以及一些I/O空間了,爲了解決這個問題,在x86處理器平臺設置了一個經驗值:896MB,就是說,如果系統中的物理內存(包括內存孔洞)大於896MB,那麼將前896MB物理內存固定映射到內核邏輯地址空間0xC0000000~0xC0000000+896MB=high_memory)上,而896MB之後的物理內存則不建立到內核線性地址空間的固定映射,這部分內存就叫高端物理內存。此時內核線性地址空間high_memory~0xFFFFFFFF之間的128MB空間就稱爲高端內存線性地址空間,用來映射高端物理內存和I/O空間。896MBx86處理器平臺的經驗值,留了128MB線性地址空間來映射高端內存以及I/O地址空間,在嵌入式系統中可以根據具體情況修改這個閾值,比如,MIPS中將這個值設置爲0x20000000B512MB),那麼只有當系統中的物理內存空間容量大於0x20000000B時,內核才需要配置CONFIG_HIGHMEM選項,使能內核對高端內存的分配和映射功能。什麼情況需要劃分出高端物理內存以及高端物理內存閾值的設置原則見上面的內存頁區(zone)概念說明。

 

8)高端線性地址空間:從high_memory0xFFFFFFFF之間的線性地址空間屬於高端線性地址空間,其中VMALLOC_START~VMALLOC_END之間線性地址:(1)被vmalloc()函數用來分配物理上不連續但線性地址空間連續的高端物理內存,或者(2)被vmap()函數用來映射高端或低端物理內存,或者(3)由ioremap()函數來重新映射I/O物理空間。其中PKMAP_BASE開始的LAST_PKMAP(一般等於1024)頁線性地址空間:被kmap()函數用來永久映射高端物理內存。FIXADDR_START開始的KM_TYPE_NR*NR_CPUS頁線性地址空間:被kmap_atomic()函數用來臨時映射高端物理內存,其他未用高端線性地址空間可以用來在系統初始化期間永久映射I/O地址空間。

 

Linux 2.6.10內核中的ARM處理器平臺部分沒有對高端內存的支持 

轉載於:http://blog.csdn.net/do2jiang/archive/2010/04/17/5495685.aspx

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