咱們都知道在用戶空間動態申請內存用的函數是 malloc(),這個函數在各類操做系統上的使用是一致的,對應的用戶空間內存釋放函數是 free()。html
注意:動態申請的內存使用完後必需要釋放,不然會形成內存泄漏,若是內存泄漏發生在內核空間,則會形成系統崩潰。 函數
那麼,在內核空間中如何申請內存呢?通常咱們會用到 kmalloc()、kzalloc()、vmalloc() 等,下面咱們介紹一下這些函數的使用以及它們之間的區別。性能
kmalloc()ui
函數原型:
void *kmalloc(size_t size, gfp_t flags);spa
kmalloc() 申請的內存位於物理內存映射區域,並且在物理上也是連續的,它們與真實的物理地址只有一個固定的偏移,由於存在較簡單的轉換關係,因此對申請的內存大小有限制,不能超過128KB。 操作系統
較經常使用的 flags(分配內存的方法):code
flags 的參考用法:
|– 進程上下文,能夠睡眠 GFP_KERNEL
|– 進程上下文,不能夠睡眠 GFP_ATOMIC
| |– 中斷處理程序 GFP_ATOMIC
| |– 軟中斷 GFP_ATOMIC
| |– Tasklet GFP_ATOMIC
|– 用於DMA的內存,能夠睡眠 GFP_DMA | GFP_KERNEL
|– 用於DMA的內存,不能夠睡眠 GFP_DMA |GFP_ATOMIC htm
成功返回分配的目標內存空間的首地址;失敗返回NULL.
對應的內存釋放函數爲:進程
void kfree(const void *objp);
kzalloc()
/** * kzalloc - allocate memory. The memory is set to zero. * @size: how many bytes of memory are required. * @flags: the type of memory to allocate (see kmalloc). */static inline void *kzalloc(size_t size, gfp_t flags){ return kmalloc(size, flags | __GFP_ZERO);} kzalloc() 函數與 kmalloc() 很是類似,參數及返回值是同樣的,能夠說是前者是後者的一個變種,由於 kzalloc() 實際上只是額外附加了 __GFP_ZERO 標誌。因此它除了申請內核內存外,還會對申請到的內存內容清零。內存
kzalloc() 對應的內存釋放函數也是 kfree()。
vmalloc()
函數原型:
void *vmalloc(unsigned long size);
vmalloc() 函數則會在虛擬內存空間給出一塊連續的內存區,但這片連續的虛擬內存在物理內存中並不必定連續。因爲 vmalloc() 沒有保證申請到的是連續的物理內存,所以對申請的內存大小沒有限制,若是須要申請較大的內存空間就須要用此函數了。
對應的內存釋放函數爲:
void vfree(const void *addr);
注意:vmalloc() 和 vfree() 能夠睡眠,所以不能從中斷上下文調用。
總結
用於申請內核空間的內存;kmalloc()、kzalloc()、vmalloc() 的共同特色是:
kmalloc()、kzalloc()、vmalloc() 的區別是:
通常狀況下,內存只有在要被 DMA 訪問的時候才須要物理上連續,但爲了性能上的考慮,內核中通常使用 kmalloc(),而只有在須要得到大塊內存時才使用 vmalloc()。例如,當模塊被動態加載到內核當中時,就把模塊裝載到由 vmalloc() 分配的內存上。