天天看點

記憶體管理相關知識

        對于32位的系統,它的尋址空間為4GiB,linux系統通常會把這個4GiB的虛拟位址空間按3:1進行配置設定,即前面3GiB用于使用者空間,後而1GiB用于核心空間。

        使用者空間通過中斷異常或系統調用切換到核心空間,使用者空間通路記憶體時,它不會直接去通路實體記憶體,而是通過頁表機制去通路,虛拟位址與實體位址之間的關系如圖1所示:

記憶體管理相關知識

圖1 32位處理上虛拟位址與實體位址之間關系

        如圖1所示,實體記憶體被映射到核心空間,如使用者空間要對實體記憶體進行通路,它是通過頁表來進行通路的,使用者空間用的是虛拟位址。根據實作實體記憶體大小,将實體記憶體映射到核心空間後,還會對核心位址空間進行劃分,32位系統上記憶體位址空間劃分如圖2所示:

記憶體管理相關知識

圖2 32位系統上核心空間劃分

        根據3:1劃分虛拟記憶體空間後,核心空間的地始位址__PAGE_OFFSET從0xc000000開始,将實體記憶體映射到__PAGE_OFFSET開始的地方,這塊區域是記憶體直接映射區域,這部分對應的虛拟位址x,它和實體位址之間存在 一個簡單的線性平移,這部分的虛拟位址和實體位址可以通過兩個宏進行轉換:

#define __pa(x) ((unsigned long (x) - PAGE_OFFSET)   傳回虛拟位址對應的實體位址;

#define __va(x) ((void *) (unsigned long)(x) + PAGE_OFFSET)   傳回實體位址對應的虛拟位址;

        在32系統中以3:1配置設定比例配置設定核心和使用者空間的,由于核心空間的虛拟位址最大隻有1GiB,是以最多隻能映射1GiB,而且由于在核心空間裡需要留出一些虛拟位址空間來做其它目的,可以直接映射的實體記憶體隻有896MB,從__PAGE_OFFSET到high_memory最大隻有896MB,剩下high_memory開始的虛拟記憶體空間用于管理vmalloc記憶體管理,持久 映射和固定映射。如剩下的虛拟記憶體空間為128MiB,通常在high_memory開始外會有8MiB的記憶體安全隙,防止不正常的記憶體不通路。

         在核心中也有與C标準庫中用于申請和釋放記憶體的函數存在,它們分别是:

kmalloc(size,flags),size為要申請的記憶體大小,flags為申請記憶體時指定的标志,用于指定用于配置設定記憶體的記憶體域(DMA,Normal, highmem),或用于指定記憶體配置設定器的行為,如__GFP_WAIT表示配置設定記憶體時可以等待和排程,__GFP_HIGH表示記憶體配置設定時不能被中斷,用于原子配置設定。

kfree(ptr),ptr是指向由kmalloc申請的記憶體。

         kmalloc是基于slab配置設定器的一種記憶體管理方式,也就是說得先用kmem_cache_create來建立一個記憶體緩存,然後再通過kmem_cache_alloc和kmem_cache_free來申請記憶體。

         通過kmalloc申請記憶體時,有可能得到多于你申請記憶體大小,由它申請的記憶體長度都是2的幂次,範圍2的5次32位元組(記憶體頁為4096)或64位元組到2的25次32M位元組,上限可以通過KMALLOC_MAX_SIZE設定,預設上限為128K位元組,上限它是根據系統頁大小和最大允許的配置設定階計算:

#define  KALLOC_SHIFT_HIGH    ((MAX_ORKER + PAGE_SHIFT -1) <= 25 ? (MAX_ORDER + PAGE_SHIFT -1) : 25) 

#define KMALLOC_MAX_SIZE     (1UL << KMALLOC_SHIFT_HIGH)

          在調用 kmalloc申請記憶體時,記憶體會根據配置設定記憶體size找到slab配置設定器中合适的大小,然後再根據這個大小,從緩存中配置設定記憶體;如果不能找到合适的大小,最會配置設定稍大小size的記憶體,但不會配置設定小于size的記憶體。

          通過上面的kmalloc配置設定記憶體時,得到的連續的實體記憶體,當系統運作很長間後,由于記憶體碎片等原因,很難再去配置設定 一個很大的連續實體記憶體,核心可以和使用者空間一樣通過申請虛拟記憶體空間,然後通過分頁機制去通路實際記憶體來解決這個問題。在核心中,有專門用于申請實體記憶體不連續,但虛拟記憶體連續的記憶體空間:

void * vmalloc(unsigned long size);

         對于vmalloc它隻要指定配置設定的虛拟記憶體大小就行。由vmalloc配置設定得到的是連續的虛拟記憶體,但實體記憶體不一定是連續的,由于低端記憶體域的記憶體相對比較寶貴,不應該浪費在vmalloc配置設定中,是以在由vmalloc配置設定記憶體時,通常是從zone_highmem記憶體域配置設定,也就是說從highmem配置設定虛拟記憶體的優先級高于normal和dma記憶體域。

         由vmalloc配置設定記憶體時分為3個步驟:首先找到一個合适的記憶體域;然後從這個記憶體域中配置設定實體記憶體;最後将這些實體記憶體連續的映射到vmalloc區域。