IT貓撲網(wǎng):您身邊最放心的安全下載站! 最新更新|軟件分類|軟件專題|手機版|論壇轉(zhuǎn)貼|軟件發(fā)布

您當前所在位置:首頁操作系統(tǒng)LINUX → Linux高端內(nèi)存

Linux高端內(nèi)存

時間:2015/6/28來源:IT貓撲網(wǎng)作者:網(wǎng)管聯(lián)盟我要評論(0)

  高端內(nèi)存是指物理地址大于 896M 的內(nèi)存。

  對于這樣的內(nèi)存,無法在"內(nèi)核直接映射空間"進行映射。

  為什么?

  因為"內(nèi)核直接映射空間"最多只能從 3G 到 4G,只能直接映射 1G 物理內(nèi)存,對于大于 1G 的物理內(nèi)存,無能為力。

  實際上,"內(nèi)核直接映射空間"也達不到 1G, 還得留點線性空間給"內(nèi)核動態(tài)映射空間" 呢。

  因此,Linux 規(guī)定"內(nèi)核直接映射空間" 最多映射 896M 物理內(nèi)存。

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

  高端內(nèi)存映射有三種方式:

  1、映射到"內(nèi)核動態(tài)映射空間"

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

  2、永久內(nèi)核映射

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

  內(nèi)核專門為此留出一塊線性空間,從 PKMAP_BASE 到 FIXADDR_START ,用于映射高端內(nèi)存。在 2.4 內(nèi)核上,這個地址范圍是 4G-8M 到 4G-4M 之間。這個空間起叫"內(nèi)核永久映射空間"或者"永久內(nèi)核映射空間"

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

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

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

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

  3、臨時映射

  內(nèi)核在 FIXADDR_START 到 FIXADDR_TOP 之間保留了一些線性空間用于特殊需求。這個空間稱為"固定映射空間"

  在這個空間中,有一部分用于高端內(nèi)存的臨時映射。

  這塊空間具有如下特點:

  1、 每個 CPU 占用一塊空間

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

  當要進行一次臨時映射的時候,需要指定映射的目的,根據(jù)映射目的,可以找到對應(yīng)的小空間,然后把這個空間的地址作為映射地址。這意味著一次臨時映射會導(dǎo)致以前的映射被覆蓋。

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

  下圖簡單簡單表達如何對高端內(nèi)存進行映射

 。

  高端內(nèi)存含義為:線性地址空間 PAGE_OFFSET + 896M 至4G的最后128M線性地址 <==映射==> 896M以上的物理頁框,非直接映射。有3種方法:非連續(xù)內(nèi)存區(qū)映射,永久內(nèi)核映射,臨時內(nèi)核映射(固定映射)

  從 PAGE_OFFSET開始的線性地址區(qū)域為:

  PAGE_OFFSET(3G)|物理內(nèi)存映射 --8M-- vmalloc區(qū) --4K-- vmalloc區(qū) --8K-- 永久內(nèi)核映射--臨時內(nèi)核映射(固定映射)|4G

  1. 非連續(xù)區(qū)映射

  1.1 每個非連續(xù)內(nèi)存區(qū)都對應(yīng)一個類型為 vm_struct的描述符,通過next字段,這些描述符被插入到一個vmlist鏈表中。

  1.2 三種非連續(xù)區(qū)的類型:

  VM_ALLOC   -- 物理內(nèi)存(調(diào)用alloc_page)和線性地址同時申請,物理內(nèi)存是 __GFP_HIGHMEM類型(分配順序是HIGH, NORMAL, DMA )(可見vmalloc不僅僅可以映射__GFP_HIGHMEM頁框,它的主要目的是為了將零散的,不連續(xù)的頁框拼湊成連續(xù)的內(nèi)核邏輯地址空間...)

  VM_MAP     -- 僅申請線性區(qū),物理內(nèi)存另外申請,是VM_ALLOC的簡化版

  VM_IOREMAP -- 僅申請線性區(qū),物理內(nèi)存另外申請(這里的物理內(nèi)存一般都是高端內(nèi)存,大于896M的內(nèi)存)

  2. 永久內(nèi)核映射

  2.1 永久內(nèi)存映射允許建立長期映射。使用主內(nèi)核頁表中swapper_pg_dir的一個專門頁表。

  pkmap_page_table: 專門的頁表。頁表表項數(shù)由LAST_PKMAP(512或1024)產(chǎn)生。

  page_address_htable: 存放地址的

  pkmap_count: 包含LAST_PKMAP個計數(shù)器的數(shù)組。

  PKMAP_BASE: 頁表線性地址從PKMAP_BASE開始。

  2.2 如果LAST_PKMAP個項都用完,則把當前進程置為 TASK_UNINTERRUPTIBLE,并調(diào)用schedule()

  3. 臨時內(nèi)存映射

  3.1 可以用在中斷處理函數(shù)和可延遲函數(shù)的內(nèi)部,從不阻塞。因為臨時內(nèi)存映射是固定內(nèi)存映射的一部分,一個地址固定給一個內(nèi)核成分使用。

  3.2 每個CPU都有自己的一個13個窗口(一個線性地址及頁表項)的集合。

  enum km_type {

  KM_BOUNCE_READ,

  KM_SKB_SUNRPC_DATA,

  KM_SKB_DATA_SOFTIRQ,

  KM_USER0,

  KM_USER1,

  KM_BIO_SRC_IRQ,

  KM_BIO_DST_IRQ,

  KM_PTE0,

  KM_PTE1,

  KM_IRQ0,

  KM_IRQ1,

  KM_SOFTIRQ0,

  KM_SOFTIRQ1,

  KM_TYPE_NR

  };

  所有固定映射的固定線性地址

  enum fixed_addresses {

  FIX_HOLE,

  FIX_VSYSCALL,

  ....

  #ifdef CONFIG_HIGHMEM

  FIX_KMAP_BEGIN,    /* reserved pte's for temporary kernel mappings */

  FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,

  #endif

  .......

  __end_of_permanent_fixed_addresses,

  /* temporary boot-time mappings, used before ioremap() is functional */

  #define NR_FIX_BTMAPS    16

  FIX_BTMAP_END = __end_of_permanent_fixed_addresses,

  FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,

  FIX_WP_TEST,

  __end_of_fixed_addresses

  };

  3.3 注意 fixed_addresses 的地址從上至下是倒著的,F(xiàn)IX_HOLE的地址等于 0xfffff000,是一個洞

  #define __fix_to_virt(x)    (FIXADDR_TOP - ((x) << PAGE_SHIFT))

  #define __FIXADDR_TOP    0xfffff000

 。

  VMALLOC_RESERVE和896M

  LINUX 內(nèi)核虛擬地址空間到物理地址空間一般是固定連續(xù)影射的。

  假定機器內(nèi)存為512M,

  從 3G開始,到3G + 512M 為連續(xù)固定影射區(qū)。zone_dma, zone_normal為這個區(qū)域的。固定影射的VADDR可以直接使用(get a free page, then use pfn_to_virt()等宏定義轉(zhuǎn)換得到vaddr)或用kmalloc等分配. 這樣的vaddr的物理頁是連續(xù)的。得到的地址也一定在固定影射區(qū)域內(nèi)。

  如果內(nèi)存緊張,連續(xù)區(qū)域無法滿足,調(diào)用vmalloc分配是必須的,因為它可以將物理不連續(xù)的空間組合后分配,所以更能滿足分配要求。vmalloc可以映射高端頁框,也可以映射底端頁框。vmalloc的作用只是為了提供邏輯上連續(xù)的地址。。。

  但 vmalloc分配的vaddr一定不能與固定影射區(qū)域的vaddr重合。因為vaddr到物理頁的影射同時只能唯一。所以vmalloc得到的 vaddr要在3G + 512m 以上才可以。也就是從VMALLOC_START開始分配。 VMALLOC_START比連續(xù)固定影射區(qū)大最大vaddr地址還多8-16M(2*VMALLOC_OFFSET)--有個鬼公式在

  #define VMALLOC_OFFSET   8*1024

  #define VMALLOC_START   (high_memory - 2*VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)

  high_memory 就是固定影射區(qū)域最高處。

  空開8-16M做什么? 為了捕獲越界的mm_fault.

  同樣,vmalloc每次得到的VADDR空間中間要留一個PAGE的空(空洞),目的和上面的空開一樣。你vmalloc(100)2次,得到的2個地址中間相距8K。

  如果連續(xù)分配無空洞,那么比如

  p1=vmalloc(4096);

  p2=vmalloc(4096);

  如果p1使用越界到p2中了,也不會mm_falut. 那不容易debug.

  下面說明VMALLOC_RESERVE和896M的問題。

  上面假設(shè)機器物理512M的case. 如果機器有1G物理內(nèi)存如何是好?那vmalloc()的vaddr是不是要在3G + 1G + 8M 空洞以上分配?超過尋址空間了嗎。

  這時,4G 下面保留的VMALLOC_RESERVE 128m 就派上用場了。

  也就是說如果物理內(nèi)存超過896M, high_memory也只能在3G + 896地方。可尋址空間最高處要保留VMALLOC_RESREVE 128M給vmalloc用。

  所以這128M的VADDR空間是為了vmalloc在物理超過了896M時候使用。如果物理僅僅有512M, 一般使用不到。因為VMALLOC_START很低了。如果vmalloc太多了才會用到。

  high_memory在arch/i386/kernel, mm的初始化中設(shè)置。根據(jù)物理內(nèi)存大小和VMALLOC_RESERVE得到數(shù)值.

  所以說那128M的內(nèi)核線性地址僅僅是為了影

關(guān)鍵詞標簽:Linux

相關(guān)閱讀

文章評論
發(fā)表評論

熱門文章 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程使用screen管理你的遠程會話使用screen管理你的遠程會話GNU/Linux安裝vmwareGNU/Linux安裝vmware如何登錄linux vps圖形界面 Linux遠程桌面連如何登錄linux vps圖形界面 Linux遠程桌面連

相關(guān)下載

人氣排行 Linux下獲取CPUID、硬盤序列號與MAC地址linux tc實現(xiàn)ip流量限制dmidecode命令查看內(nèi)存型號linux下解壓rar文件安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程Ubuntu linux 關(guān)機、重啟、注銷 命令lcx.exe、nc.exe、sc.exe入侵中的使用方法查看linux服務(wù)器硬盤IO讀寫負載