Linux內存管理-高端內存

      上一週一直在關注linux內存中3:1(3G:1G)的關係,並沒有考慮到如果我的物理內存大於1G,那麼內核空間1G的虛擬空間如何映射整個物理內存呢?以及內核是如何管理這大於1G的物理內存的。

 

下面是轉載的文章,解釋了這個疑問。

 

高端內存是指物理地址大於 896M 的內存。對於這樣的內存,無法在“內核直接映射空間”進行映射。


爲什麼?

  因爲“內核直接映射空間”最多隻能從 3G 到 4G,只能直接映射 1G 物理內存,對於大於 1G 的物理內存,無能爲力

  實際上,“內核直接映射空間”也達不到 1G, 還得留點線性空間給“內核動態映射空間” 呢。

  因此,Linux 規定“內核直接映射空間” 最多映射 896M 物理內存

  對於高端內存,可以通過 alloc_page() 或者其它函數獲得對應的 page,但是要想訪問實際物理內存,還得把 page 轉爲線性地址才行(爲什麼?想想 MMU 是如何訪問物理內存的),也就是說,我們需要爲高端內存對應的 page 找一個線性空間,這個過程稱爲高端內存映射。


高端內存映射有三種方式:


1、映射到“內核動態映射空間”

  這種方式很簡單,因爲通過 vmalloc() ,在“內核動態映射空間”申請內存的時候,就可能從高端內存獲得頁面(參看 vmalloc 的實現),因此說高端內存有可能映射到“內核動態映射空間” 中


2、永久內核映射

  如果是通過 alloc_page() 獲得了高端內存對應的 page,如何給它找個線性空間?

  內核專門爲此留出一塊線性空間,從 PKMAP_BASE 到 FIXADDR_START ,用於映射高端內存。在 2.4 內核上,這個地址範圍是 4G-8M 到 4G-4M 之間。這個空間起叫“內核永久映射空間”或者“永久內核映射空間”

  這個空間和其它空間使用同樣的頁目錄表,對於內核來說,就是 swapper_pg_dir,對普通進程來說,通過 CR3 寄存器指向。

  通常情況下,這個空間是 4M 大小,因此僅僅需要一個頁表即可,內核通過來 pkmap_page_table 尋找這個頁表。

  通過 kmap(), 可以把一個 page 映射到這個空間來

  由於這個空間是 4M 大小,最多能同時映射 1024 個 page。因此,對於不使用的的 page,應該及時從這個空間釋放掉(也除映射關就是解系),通過 kunmap() ,可以把一個 page 對應的線性地址從這個空間釋放出來。


3、臨時映射

  內核在 FIXADDR_START 到 FIXADDR_TOP 之間保留了一些線性空間用於特殊需求。這個空間稱爲“固定映射空間

  在這個空間中,有一部分用於高端內存的臨時映射。

  這塊空間具有如下特點:

  1、 每個 CPU 佔用一塊空間

  2、 在每個 CPU 佔用的那塊空間中,又分爲多個小空間,每個小空間大小是 1 個 page,每個小空間用於一個目的,這些目的定義在 kmap_types.h 中的 km_type 中。

  當要進行一次臨時映射的時候,需要指定映射的目的,根據映射目的,可以找到對應的小空間,然後把這個空間的地址作爲映射地址。這意味着一次臨時映射會導致以前的映射被覆蓋。

  通過 kmap_atomic() 可實現臨時映射。

      下圖簡單簡單表達如何對高端內存進行映射

 

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/do2jiang/archive/2010/04/17/5495675.aspx

 

 

Linux內存線性地址空間大小爲4GB,分爲2個部分:用戶空間部分(通常是3G)和內核空間部分(通常是1G)。在此我們主要關注內核地址空間部分。

內核通過內核頁全局目錄來管理所有的物理內存,由於線性地址前3G空間爲用戶使用,內核頁全局目錄前768項(剛好3G)除0、1兩項外全部爲0,後256項(1G)用來管理所有的物理內存。內核頁全局目錄在編譯時靜態地定義爲swapper_pg_dir數組,該數組從物理內存地址0x101000處開始存放。

 

      由圖可見,內核線性地址空間部分從PAGE_OFFSET(通常定義爲3G)開始,爲了將內核裝入內存,從PAGE_OFFSET開始8M線性地址用來映射內核所在的物理內存地址(也可以說是內核所在虛擬地址是從PAGE_OFFSET開始的);接下來是mem_map數組,mem_map的起始線性地址與體系結構相關,比如對於UMA結構,由於從PAGE_OFFSET開始16M線性地址空間對應的16M物理地址空間是DMA區,mem_map數組通常開始於PAGE_OFFSET+16M的線性地址;從PAGE_OFFSET開始到VMALLOC_START – VMALLOC_OFFSET的線性地址空間直接映射到物理內存空間(一一對應影射,物理地址<==>線性地址-PAGE_OFFSET),這段區域的大小和機器實際擁有的物理內存大小有關,這兒VMALLOC_OFFSET在X86上爲8M,主要用來防止越界錯誤;在內存比較小的系統上,餘下的線性地址空間(還要再減去空白區即VMALLOC_OFFSET)被vmalloc()函數用來把不連續的物理地址空間映射到連續的線性地址空間上,在內存比較大的系統上,vmalloc()使用從VMALLOC_START到VMALLOC_END(也即PKMAP_BASE減去2頁的空白頁大小PAGE_SIZE(解釋VMALLOC_END))的線性地址空間,此時餘下的線性地址空間(還要再減去2頁的空白區即VMALLOC_OFFSET)又可以分成2部分:第一部分從PKMAP_BASE到FIXADDR_START用來由kmap()函數來建立永久映射高端內存;第二部分,從FIXADDR_START到FIXADDR_TOP,這是一個固定大小的臨時映射線性地址空間,(引用:Fixed virtual addresses are needed for subsystems that need to know the virtual address at compile time such as the APIC),在X86體系結構上,FIXADDR_TOP被靜態定義爲0xFFFFE000,此時這個固定大小空間結束於整個線性地址空間最後4K前面,該固定大小空間大小是在編譯時計算出來並存儲在__FIXADDR_SIZE變量中。

      正是由於vmalloc()使用區、kmap()使用區及固定大小區(kmap_atomic()使用區)的存在才使ZONE_NORMAL區大小受到限制,由於內核在運行時需要這些函數,因此在線性地址空間中至少要VMALLOC_RESERVE大小的空間。VMALLOC_RESERVE的大小與體系結構相關,在X86上,VMALLOC_RESERVE定義爲128M,這就是爲什麼ZONE_NORMAL大小通常是16M到896M的原因。

 

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/do2jiang/archive/2010/04/17/5495678.aspx

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