本文主要介紹內存申請的函數介紹:
1.vmalloc kmalloc 是用來分配內核空間內存的,malloc是用來分配用戶空間的內存的。kmalloc分配的頁在物理地址上是連續的(虛擬地址自然也是連續的),
vmalloc只確保
頁在虛擬地址空間內是連續的。它通過非連續的物理內存塊,再“修正”頁表,把內存映射到邏輯地址空間是連續的區域內。 malloc
返回的也在進程的虛擬地址空間內是連續
的,但是在物理地址上不一定是連續的。
2. 用於kmalloc可分配的內存大小范圍在32~131027(128k)字節,並且由於它用slab分配器來分配內存的,所以,得到的內存大小可能比你申請的要大一些(它向上取2的N次冪整數)。而且如果開啟了CONFIG_LARGE_ALLOCS選項,這個值可以更大,可以達到了32M。一般申請較大的內存才使用vmalloc,例如當模塊被動態加載到內核當中時,
就把模塊裝載到由vmalloc()分配 的內存上。
3.vmalloc是會睡眠的,因此不能在中斷上下文中使用。 kmalloc可以通過配置flags配置為可睡眠或者不可睡眠,GFP_KERNEL可以睡眠 ,GFP_ATOMIC不可以睡眠。
4.內核中vmalloc,kmalloc分配都是以字節為單位,若想以頁為單位用alloc_pages類函數。 當然,內核進行內存管理(MMU干的)是以物理頁為基本單位的。
簡單的說:
kmalloc和vmalloc是分配的是內核的內存,malloc分配的是用戶的內存
kmalloc保證分配的內存在物理上是連續的,vmalloc保證的是在虛擬地址空間上的連續,malloc不保證任何東西(猜測的,不一定正確)
kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相對較大
內存只有在要被DMA訪問的時候才需要物理上連續
vmalloc比kmalloc要慢
kmalloc()是內核中最常見的內存分配方式,它最終調用伙伴系統的__get_free_pages()函數分配,根據傳遞給這個函數的flags參數,決定這個函數的分配適合什麼場合,如果標志是GFP_KERNEL則僅僅可以用於進程上下文中,如果標志GFP_ATOMIC則可以用於中斷上下文或者持有鎖的代碼段中。kmalloc返回的線形地址是直接映射的,而且用連續物理頁滿足分配請求,且內置了最大請求數(2**5=32頁)。
vmalloc優先使用高端物理內存,但性能上會打些折扣。
vmalloc分配的物理頁不會被交換出去;
vmalloc返回的虛地址大於(PAGE_OFFSET + SIZEOF(phys memory) + GAP),為VMALLOC_START----VMALLOC_END之間的線形地址;
vmalloc使用的是vmlist鏈表,與管理用戶進程的vm_area_struct要區別,而後者會swapped;
kmap()是主要用在高端存儲器頁框的內核映射中,一般是這麼使用的:
使用alloc_pages()在高端存儲器區得到struct page結構,然後調用kmap(struct *page)在內核地址空間PAGE_OFFSET+896M之後的地址空間中(PKMAP_BASE到FIXADDR_STAR)建立永久映射(如果page結構對應的是低端物理內存的頁,該函數僅僅返回該頁對應的虛擬地址)
kmap()也可能引起睡眠,所以不能用在中斷和持有鎖的代碼中
不過kmap 只能對一個物理頁進行分配,所以盡量少用。
對於高端物理內存(896M之後),並沒有和內核地址空間建立一一對應的關系(即虛擬地址=物理地址+PAGE_OFFSET這樣的關系),所以不能使用get_free_pages()這樣的頁分配器進行內存的分配,而必須使用alloc_pages()這樣的伙伴系統算法的接口得到struct *page結構,然後將其映射到內核地址空間,注意這個時候映射後的地址並非和物理地址相差PAGE_OFFSET.
kmalloc和get_free_page申請的內存位於物理內存映射區域,而且在物理上也是連續的,它們與真實的物理地址只有一個固定的偏移,因此存在較簡單的轉換關系。而vmalloc申請的內存則位於vmalloc_start~vmalloc_end之間,與物理地址沒有簡單的轉換關系,雖然在邏輯上它們也是連續的,但是在物理上它們不要求連續。
kmalloc()和vmalloc()介紹
kmalloc()
用於申請較小的、連續的物理內存
1. 以字節為單位進行分配,在<linux/slab.h>中
2. void *kmalloc(size_t size, int flags)分配的內存物理地址上連續,虛擬地址上自然連續
3. gfp_mask標志:什麼時候使用哪種標志?如下:
———————————————————————————————-
情形 相應標志
———————————————————————————————-
進程上下文,可以睡眠 GFP_KERNEL
進程上下文,不可以睡眠 GFP_ATOMIC
中斷處理程序 GFP_ATOMIC
軟中斷 GFP_ATOMIC
Tasklet GFP_ATOMIC
用於DMA的內存,可以睡眠 GFP_DMA| GFP_KERNEL
用於DMA的內存,不可以睡眠 GFP_DMA| GFP_ATOMIC
———————————————————————————————-
4. void kfree(const void *ptr)
釋放由kmalloc()分配出來的內存塊
vmalloc()
用於申請較大的內存空間,虛擬內存是連續的
1. 以字節為單位進行分配,在<linux/vmalloc.h>中
2. void *vmalloc(unsigned long size)分配的內存虛擬地址上連續,物理地址不連續
3.一般情況下,只有硬件設備才需要物理地址連續的內存,因為硬件設備往往存在於MMU之外,根本不了解虛擬地址;但為了性能上的考慮,內核中一般使用kmalloc(),而只有在需要獲得大塊內存時才使用vmalloc(),例如當模塊被動態加載到內核當中時,就把模塊裝載到由vmalloc()分配 的內存上。
4.void vfree(void *addr),這個函數可以睡眠,因此不能從中斷上下文調用。
malloc(), vmalloc()和kmalloc()區別
[*]kmalloc和vmalloc是分配的是內核的內存,malloc分配的是用戶的內存
[*]kmalloc保證分配的內存在物理上是連續的,vmalloc保證的是在虛擬地址空間上的連續,malloc不保證任何東西(這點是自己猜測的,不一定正確)
[*]kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相對較大
[*]內存只有在要被DMA訪問的時候才需要物理上連續
[*]vmalloc比kmalloc要慢