kmalloc ? vmalloc ? kzalloc ? get_free_page()是內核空間申請內存空間函數
malloc是用戶空間申請內存函數
?
一 ,kmalloc()?與 kfree()? 和get_free_page的區別
1,用于申請較小的、連續的物理內存:使用的是內存分配器slab一小片。申請的內存位于物理內存的映射區域。其正真的物理地址只相差一個固定的偏移。
?? 可以用這兩個宏來簡單轉換 __pa(address)??{virt_to_phys()} 和 ?__va(address){phys_to_virt()}
?? get_free_page()申請的內存是一整頁,一頁的大小一般是128K。它們的區別只有這一點不同,其它的都相同。
?? 本質上講,kmalloc()和get_free_page()最終調用實現都是相同的,只不過在調用最終函數時所傳的flag不同而以。
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() 與 vfree()
用于申請較大的內存空間,虛擬內存是連續的:申請內存位于vmalloc_start -----vmalloc_end之間,與物理內存沒有簡單的轉換關系。物理上不要求連續。
1. 以字節為單位進行分配,在<linux/vmalloc.h>中
2. void *vmalloc(unsigned long size) 分配的內存虛擬地址上連續,物理地址不連續
3. 一般情況下,只有硬件設備才需要物理地址連續的內存,因為硬件設備往往存在于MMU之外,根本不了解虛擬地址;但為了性能上的考慮,內核中一般使用kmalloc(),而只有在需要獲得大塊內存時才使用vmalloc(),例如當模塊被動態加載到內核當中時,就把模塊裝載到由vmalloc()分配的內存上。
4.void vfree(void *addr),這個函數可以睡眠,因此不能從中斷上下文調用。
三,malloc(), vmalloc()和kmalloc()區別
[1]kmalloc和vmalloc是分配的是內核的內存,malloc分配的是用戶的內存
[2]kmalloc保證分配的內存在物理上是連續的,vmalloc保證的是在虛擬地址空間上的連續,malloc和vmalloc一樣,也是虛連,物理不一定連。
[3]kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相對較大
[4]內存只有在要被DMA訪問的時候才需要物理上連續
[5]vmalloc比kmalloc要慢
?
四,kzalloc
kzalloc實現了kmalloc以及memset的功能,一個函數起到了兩個函數的作用
?這個函數就是原來的兩個函數的整合?,?即原來我們每次申請內存的時候都會這么做?,?先是用?kmalloc()?申請空間?,?然后用memset()?來初始化?,?而現在省事了?,?一步到位?,?直接調用kzalloc(),?效果等同于原來那兩個函數?,?所有申請的元素都被初始化為?0.?其實對寫驅動的來說?,?知道現在應該用?kzalloc()?代替原來的?kmalloc()?和?memset()?就可以了?,?這是內核中內存管理部分做出的改變?,?確切的說是改進?,?負責內存管理那部分的兄弟們的目標無非就是讓內核跑起來更快一些?,?而從?kmalloc/memset?到kzalloc?的改變確實也是為了實現這方面的優化.
五,目前kzalloc將取代kmalloc和memset功能。
?以后在內核,看到此函數的比率將會更高。