linux核心地址對映模型 x86 CPU採用了段頁式地址對映模型。程序程式碼中的地址為邏輯地址,經過段頁式地址對映後,才真正訪問物理記憶體。 段頁式機制如下圖。 linux核心地址空間劃分 通常32位linux核心地址空間劃分0~3G為使用者空間,3~4G為核心空間。注意這裡是32位核心地址空間劃分,64位核心地址空間劃分是不同的。 linux核心高階記憶體的由來 當核心模組程式碼或執行緒訪問記憶體時,程式碼中的記憶體地址都為邏輯地址,而對應到真正的物理記憶體地址,需要地址一對一的對映,如邏輯地址0xc0000003對應的物理地址為0×3,0xc0000004對應的物理地址為0×4,… …,邏輯地址與物理地址對應的關係為 物理地址 = 邏輯地址 0xC0000000 邏輯地址物理記憶體地址0xc00000000×00xc00000010×10xc00000020×20xc00000030×3… … 0xe00000000×20000000……0xffffffff0×40000000 ?? 顯然不能將核心地址空間0xc0000000 ~ 0xfffffff全部用來簡單的地址對映。因此x86架構中將核心地址空間劃分三部分:ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM。ZONE_HIGHMEM即為高階記憶體,這就是記憶體高階記憶體概念的由來。 在x86結構中,三種類型的區域如下: ZONE_DMA 記憶體開始的16MB ZONE_NORMAL 16MB~896MB ZONE_HIGHMEM 896MB ~ 結束 linux核心高階記憶體的理解 前面我們解釋了高階記憶體的由來。 linux將核心地址空間劃分為三部分ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM,高階記憶體HIGH_MEM地址空間範圍為0xF8000000 ~ 0xFFFFFFFF(896MB~1024MB)。那麼如核心是如何藉助128MB高階記憶體地址空間是如何實現訪問可以所有物理記憶體? 當核心想訪問高於896MB物理地址記憶體時,從0xF8000000 ~ 0xFFFFFFFF地址空間範圍內找一段相應大小空閒的邏輯地址空間,借用一會。借用這段邏輯地址空間,建立對映到想訪問的那段物理記憶體(即填充核心PTE頁面表),臨時用一會,用完後歸還。這樣別人也可以借用這段地址空間訪問其他物理記憶體,實現了使用有限的地址空間,訪問所有所有物理記憶體。如下圖。 例如核心想訪問2G開始的一段大小為1MB的物理記憶體,即物理地址範圍為0×80000000 ~ 0x800FFFFF。訪問之前先找到一段1MB大小的空閒地址空間,假設找到的空閒地址空間為0xF8700000 ~ 0xF87FFFFF,用這1MB的邏輯地址空間對映到物理地址空間0×80000000 ~ 0x800FFFFF的記憶體。對映關係如下: 邏輯地址物理記憶體地址0xF87000000×800000000xF87000010×800000010xF87000020×80000002… …0xF87FFFFF0x800FFFFF當核心訪問完0×80000000 ~ 0x800FFFFF物理記憶體後,就將0xF8700000 ~ 0xF87FFFFF核心線性空間釋放。這樣其他程序或程式碼也可以使用0xF8700000 ~ 0xF87FFFFF這段地址訪問其他物理記憶體。 從上面的描述,我們可以知道高階記憶體的最基本思想:借一段地址空間,建立臨時地址對映,用完後釋放,達到這段地址空間可以迴圈使用,訪問所有物理記憶體。 看到這裡,不禁有人會問:萬一有核心程序或模組一直佔用某段邏輯地址空間不釋放,怎麼辦?若真的出現的這種情況,則核心的高階記憶體地址空間越來越緊張,若都被佔用不釋放,則沒有建立對映到物理記憶體都無法訪問了。
linux核心地址對映模型 x86 CPU採用了段頁式地址對映模型。程序程式碼中的地址為邏輯地址,經過段頁式地址對映後,才真正訪問物理記憶體。 段頁式機制如下圖。 linux核心地址空間劃分 通常32位linux核心地址空間劃分0~3G為使用者空間,3~4G為核心空間。注意這裡是32位核心地址空間劃分,64位核心地址空間劃分是不同的。 linux核心高階記憶體的由來 當核心模組程式碼或執行緒訪問記憶體時,程式碼中的記憶體地址都為邏輯地址,而對應到真正的物理記憶體地址,需要地址一對一的對映,如邏輯地址0xc0000003對應的物理地址為0×3,0xc0000004對應的物理地址為0×4,… …,邏輯地址與物理地址對應的關係為 物理地址 = 邏輯地址 0xC0000000 邏輯地址物理記憶體地址0xc00000000×00xc00000010×10xc00000020×20xc00000030×3… … 0xe00000000×20000000……0xffffffff0×40000000 ?? 顯然不能將核心地址空間0xc0000000 ~ 0xfffffff全部用來簡單的地址對映。因此x86架構中將核心地址空間劃分三部分:ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM。ZONE_HIGHMEM即為高階記憶體,這就是記憶體高階記憶體概念的由來。 在x86結構中,三種類型的區域如下: ZONE_DMA 記憶體開始的16MB ZONE_NORMAL 16MB~896MB ZONE_HIGHMEM 896MB ~ 結束 linux核心高階記憶體的理解 前面我們解釋了高階記憶體的由來。 linux將核心地址空間劃分為三部分ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM,高階記憶體HIGH_MEM地址空間範圍為0xF8000000 ~ 0xFFFFFFFF(896MB~1024MB)。那麼如核心是如何藉助128MB高階記憶體地址空間是如何實現訪問可以所有物理記憶體? 當核心想訪問高於896MB物理地址記憶體時,從0xF8000000 ~ 0xFFFFFFFF地址空間範圍內找一段相應大小空閒的邏輯地址空間,借用一會。借用這段邏輯地址空間,建立對映到想訪問的那段物理記憶體(即填充核心PTE頁面表),臨時用一會,用完後歸還。這樣別人也可以借用這段地址空間訪問其他物理記憶體,實現了使用有限的地址空間,訪問所有所有物理記憶體。如下圖。 例如核心想訪問2G開始的一段大小為1MB的物理記憶體,即物理地址範圍為0×80000000 ~ 0x800FFFFF。訪問之前先找到一段1MB大小的空閒地址空間,假設找到的空閒地址空間為0xF8700000 ~ 0xF87FFFFF,用這1MB的邏輯地址空間對映到物理地址空間0×80000000 ~ 0x800FFFFF的記憶體。對映關係如下: 邏輯地址物理記憶體地址0xF87000000×800000000xF87000010×800000010xF87000020×80000002… …0xF87FFFFF0x800FFFFF當核心訪問完0×80000000 ~ 0x800FFFFF物理記憶體後,就將0xF8700000 ~ 0xF87FFFFF核心線性空間釋放。這樣其他程序或程式碼也可以使用0xF8700000 ~ 0xF87FFFFF這段地址訪問其他物理記憶體。 從上面的描述,我們可以知道高階記憶體的最基本思想:借一段地址空間,建立臨時地址對映,用完後釋放,達到這段地址空間可以迴圈使用,訪問所有物理記憶體。 看到這裡,不禁有人會問:萬一有核心程序或模組一直佔用某段邏輯地址空間不釋放,怎麼辦?若真的出現的這種情況,則核心的高階記憶體地址空間越來越緊張,若都被佔用不釋放,則沒有建立對映到物理記憶體都無法訪問了。