我們都知道在用戶空間動(dòng)態(tài)申請(qǐng)內(nèi)存用的函數(shù)是 malloc(),這個(gè)函數(shù)在各種操作系統(tǒng)上的使用是一致的,對(duì)應(yīng)的用戶空間內(nèi)存釋放函數(shù)是 free()。注意:動(dòng)態(tài)申請(qǐng)的內(nèi)存使用完后必須要釋放,否則會(huì)造成內(nèi)存泄漏,如果內(nèi)存泄漏發(fā)生在內(nèi)核空間,則會(huì)造成系統(tǒng)崩潰。
那么,在內(nèi)核空間中如何申請(qǐng)內(nèi)存呢?一般我們會(huì)用到 kmalloc()、kzalloc()、vmalloc() 等,下面我們介紹一下這些函數(shù)的使用以及它們之間的區(qū)別。
kmalloc()
函數(shù)原型:
void *kmalloc(size_t size, gfp_t flags);
kmalloc() 申請(qǐng)的內(nèi)存位于物理內(nèi)存映射區(qū)域,而且在物理上也是連續(xù)的,它們與真實(shí)的物理地址只有一個(gè)固定的偏移,因?yàn)榇嬖谳^簡(jiǎn)單的轉(zhuǎn)換關(guān)系,所以對(duì)申請(qǐng)的內(nèi)存大小有限制,不能超過128KB。
較常用的 flags(分配內(nèi)存的方法):
GFP_ATOMIC —— 分配內(nèi)存的過程是一個(gè)原子過程,分配內(nèi)存的過程不會(huì)被(高優(yōu)先級(jí)進(jìn)程或中斷)打斷;
GFP_KERNEL —— 正常分配內(nèi)存;
GFP_DMA —— 給 DMA 控制器分配內(nèi)存,需要使用該標(biāo)志(DMA要求分配虛擬地址和物理地址連續(xù))。
flags 的參考用法:
|– 進(jìn)程上下文,可以睡眠GFP_KERNEL |– 進(jìn)程上下文,不可以睡眠GFP_ATOMIC ||– 中斷處理程序GFP_ATOMIC ||– 軟中斷GFP_ATOMIC ||– TaskletGFP_ATOMIC |– 用于DMA的內(nèi)存,可以睡眠GFP_DMA | GFP_KERNEL |– 用于DMA的內(nèi)存,不可以睡眠GFP_DMA |GFP_ATOMIC
對(duì)應(yīng)的內(nèi)存釋放函數(shù)為:
void kfree(const void *objp);
kzalloc()
kzalloc() 函數(shù)與 kmalloc() 非常相似,參數(shù)及返回值是一樣的,可以說是前者是后者的一個(gè)變種,因?yàn)?kzalloc() 實(shí)際上只是額外附加了__GFP_ZERO標(biāo)志。所以它除了申請(qǐng)內(nèi)核內(nèi)存外,還會(huì)對(duì)申請(qǐng)到的內(nèi)存內(nèi)容清零。
/** * 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() 對(duì)應(yīng)的內(nèi)存釋放函數(shù)也是 kfree()。
vmalloc()
函數(shù)原型:
void *vmalloc(unsigned long size);
vmalloc() 函數(shù)則會(huì)在虛擬內(nèi)存空間給出一塊連續(xù)的內(nèi)存區(qū),但這片連續(xù)的虛擬內(nèi)存在物理內(nèi)存中并不一定連續(xù)。由于 vmalloc() 沒有保證申請(qǐng)到的是連續(xù)的物理內(nèi)存,因此對(duì)申請(qǐng)的內(nèi)存大小沒有限制,如果需要申請(qǐng)較大的內(nèi)存空間就需要用此函數(shù)了。
對(duì)應(yīng)的內(nèi)存釋放函數(shù)為:
void vfree(const void *addr);
注意:vmalloc() 和 vfree() 可以睡眠,因此不能從中斷上下文調(diào)用。
總結(jié)
kmalloc()、kzalloc()、vmalloc() 的共同特點(diǎn)是:
用于申請(qǐng)內(nèi)核空間的內(nèi)存;
內(nèi)存以字節(jié)為單位進(jìn)行分配;
所分配的內(nèi)存虛擬地址上連續(xù);
kmalloc()、kzalloc()、vmalloc() 的區(qū)別是:
kzalloc 是強(qiáng)制清零的 kmalloc 操作;(以下描述不區(qū)分 kmalloc 和 kzalloc)
kmalloc 分配的內(nèi)存大小有限制(128KB),而 vmalloc 沒有限制;
kmalloc 可以保證分配的內(nèi)存物理地址是連續(xù)的,但是 vmalloc 不能保證;
kmalloc 分配內(nèi)存的過程可以是原子過程(使用 GFP_ATOMIC),而 vmalloc 分配內(nèi)存時(shí)則可能產(chǎn)生阻塞;
kmalloc 分配內(nèi)存的開銷小,因此 kmalloc 比 vmalloc 要快;
一般情況下,內(nèi)存只有在要被 DMA 訪問的時(shí)候才需要物理上連續(xù),但為了性能上的考慮,內(nèi)核中一般使用 kmalloc(),而只有在需要獲得大塊內(nèi)存時(shí)才使用 vmalloc()。例如,當(dāng)模塊被動(dòng)態(tài)加載到內(nèi)核當(dāng)中時(shí),就把模塊裝載到由 vmalloc() 分配的內(nèi)存上。
審核編輯:符乾江
-
內(nèi)存
+關(guān)注
關(guān)注
9文章
3238瀏覽量
76525 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4422瀏覽量
67867 -
malloc
+關(guān)注
關(guān)注
0文章
53瀏覽量
391
發(fā)布評(píng)論請(qǐng)先 登錄
小夜燈CE認(rèn)證怎么申請(qǐng)
申請(qǐng) FCC ID 需要哪些資料
Linux內(nèi)核伙伴系統(tǒng)內(nèi)存申請(qǐng)函數(shù)詳解:從原理到實(shí)戰(zhàn)
函數(shù)信號(hào)發(fā)生器和任意波形信號(hào)發(fā)生器區(qū)別詳解
函數(shù)指針介紹
嵌入式開發(fā)常用函數(shù)速查表
函數(shù)指針及指針函數(shù)的區(qū)別
LUA例程-常用的回調(diào)函數(shù)使用說明
發(fā)布元服務(wù)配置隱私說明
如何為印度服務(wù)器申請(qǐng)和配置反向DNS記錄?
ulog_tag_lvl_filter_set()函數(shù)無法實(shí)現(xiàn)按照文檔說明那樣實(shí)現(xiàn)按模塊過濾,怎么解決?
詳解hal_entry入口函數(shù)
C語言中的內(nèi)聯(lián)函數(shù)與宏
申請(qǐng)函數(shù)kmalloc、kzalloc、vmalloc區(qū)別說明
評(píng)論