kmalloc, vmalloc分配的内存结构
From: http://linux.chinaunix.net/techdoc/system/2008/06/16/1011365.shtml
對(duì)于提供了MMU(存儲(chǔ)管理器,輔助操作系統(tǒng)進(jìn)行內(nèi)存管理,提供虛實(shí)地址轉(zhuǎn)換等硬件支持)的處理器而言,Linux提供了復(fù)雜的存儲(chǔ)管理系統(tǒng),使得進(jìn)程所能訪問的內(nèi)存達(dá)到4GB。
進(jìn)程的4GB內(nèi)存空間被人為的分為兩個(gè)部分--用戶空間與內(nèi)核空間。用戶空間地址分布從0到3GB(PAGE_OFFSET,在0x86中它等于0xC0000000),3GB到4GB為內(nèi)核空間。
內(nèi)核空間中,從3G到vmalloc_start這段地址是物理內(nèi)存映射區(qū)域(該區(qū)域中包含了內(nèi)核鏡像、物理頁框表mem_map等等),比如我們使用的 VMware虛擬系統(tǒng)內(nèi)存是160M,那么3G~3G+160M這片內(nèi)存就應(yīng)該映射物理內(nèi)存。在物理內(nèi)存映射區(qū)之后,就是vmalloc區(qū)域。對(duì)于 160M的系統(tǒng)而言,vmalloc_start位置應(yīng)在3G+160M附近(在物理內(nèi)存映射區(qū)與vmalloc_start期間還存在一個(gè)8M的gap 來防止躍界),vmalloc_end的位置接近4G(最后位置系統(tǒng)會(huì)保留一片128k大小的區(qū)域用于專用頁面映射)
kmalloc和get_free_page申請(qǐng)的內(nèi)存位于物理內(nèi)存映射區(qū)域,而且在物理上也是連續(xù)的,它們與真實(shí)的物理地址只有一個(gè)固定的偏移,因此存在較簡(jiǎn)單的轉(zhuǎn)換關(guān)系,virt_to_phys()可以實(shí)現(xiàn)內(nèi)核虛擬地址轉(zhuǎn)化為物理地址:
? ? #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
? ? extern inline unsigned long virt_to_phys(volatile void * address)
? ? {
? ?? ??? return __pa(address);
? ? }
上面轉(zhuǎn)換過程是將虛擬地址減去3G(PAGE_OFFSET=0XC000000)。
與之對(duì)應(yīng)的函數(shù)為phys_to_virt(),將內(nèi)核物理地址轉(zhuǎn)化為虛擬地址:
? ? #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
? ? extern inline void * phys_to_virt(unsigned long address)
? ? {
? ?? ??? return __va(address);
? ? }
virt_to_phys()和phys_to_virt()都定義在include\asm-i386\io.h中。
而vmalloc申請(qǐng)的內(nèi)存則位于vmalloc_start~vmalloc_end之間,與物理地址沒有簡(jiǎn)單的轉(zhuǎn)換關(guān)系,雖然在邏輯上它們也是連續(xù)的,但是在物理上它們不要求連續(xù)。
我們用下面的程序來演示kmalloc、get_free_page和vmalloc的區(qū)別:
#include
#include
#include
MODULE_LICENSE("GPL");
unsigned char *pagemem;
unsigned char *kmallocmem;
unsigned char *vmallocmem;
int __init mem_module_init(void)
{
//最好每次內(nèi)存申請(qǐng)都檢查申請(qǐng)是否成功
//下面這段僅僅作為演示的代碼沒有檢查
pagemem = (unsigned char*)get_free_page(0);
printk("pagemem addr=%x", pagemem);
kmallocmem = (unsigned char*)kmalloc(100, 0);
printk("kmallocmem addr=%x", kmallocmem);
vmallocmem = (unsigned char*)vmalloc(1000000);
printk("vmallocmem addr=%x", vmallocmem);
return 0;
}
void __exit mem_module_exit(void)
{
free_page(pagemem);
kfree(kmallocmem);
vfree(vmallocmem);
}
module_init(mem_module_init);
module_exit(mem_module_exit);
我們的系統(tǒng)上有160MB的內(nèi)存空間,運(yùn)行一次上述程序,發(fā)現(xiàn)pagemem的地址在0xc7997000(約3G+121M)、kmallocmem地址在0xc9bc1380(約3G+155M)、vmallocmem的地址在0xcabeb000(約3G+171M)處,符合前文所述的內(nèi)存布局。
文件:
v_k_malloc.tar.bz2
大小:
6KB
下載:
下載
vmalloc和kmalloc區(qū)別
kmalloc對(duì)應(yīng)于kfree,可以分配連續(xù)的物理內(nèi)存;
vmalloc對(duì)應(yīng)于vfree,分配連續(xù)的虛擬內(nèi)存,但是物理上不一定連續(xù)。
vmalloc分配內(nèi)存的時(shí)候邏輯地址是連續(xù)的,但物理地址一般是不連續(xù)的,適用于那種一下需要分配大量內(nèi)存的情況,如insert模塊的時(shí)候。這種分配方式性能不入kmalloc。
kmalloc分配內(nèi)存是基于slab,因此slab的一些特性包括著色,對(duì)齊等都具備,性能較好。物理地址和邏輯地址都是連續(xù)的
最主要的區(qū)別是
分配大小的問題。
比如你需要28個(gè)字節(jié),那一定用KMALLOC,如果用VMALLOC,分配不多次機(jī)器就罷工了。
n
PAGE_OFFSET為3GB,high_memory為保存物理地址最高值的變量,VMALLOC_START為非連續(xù)區(qū)的起始地址
在物理地址的末尾與第一個(gè)內(nèi)存區(qū)之間插入了一個(gè)8MB的區(qū)間,這是一個(gè)安全區(qū),目的是為了“捕獲”對(duì)非連續(xù)區(qū)的非法訪問。出于同樣的理由,在其他非連續(xù)的內(nèi)存區(qū)之間也插入了4K大小的安全區(qū)。每個(gè)非連續(xù)內(nèi)存區(qū)的大小都是4096的倍數(shù)。
n? ?? ???vmalloc()與 kmalloc()都可用于分配內(nèi)存
ü? ?? ???kmalloc()分配的內(nèi)存處于3GB~high_memory之間,這段內(nèi)核空間與物理內(nèi)存的映射一一對(duì)應(yīng)
ü? ?? ???vmalloc()分配的內(nèi)存在VMALLOC_START~4GB之間,這段非連續(xù)內(nèi)存區(qū)映射到物理內(nèi)存也可能是非連續(xù)的
n? ?? ???vmalloc() 分配的物理地址無需連續(xù),而kmalloc() 確保頁在物理上是連續(xù)的
n? ?? ???盡管僅僅在某些情況下才需要物理上連續(xù)的內(nèi)存塊,但是,很多內(nèi)核代碼都調(diào)用kmalloc(),而不是用vmalloc()獲得內(nèi)存。
n? ?? ???這主要是出于性能的考慮。vmalloc()函數(shù)為了把物理上不連續(xù)的頁面轉(zhuǎn)換為虛擬地址空間上連續(xù)的頁,必須專門建立頁表項(xiàng)。還有,通過vmalloc()獲得的頁必須一個(gè)一個(gè)的進(jìn)行映射(因?yàn)樗鼈兾锢砩喜皇沁B續(xù)的),這就會(huì)導(dǎo)致比直接內(nèi)存映射大得多的緩沖區(qū)刷新。
n? ?? ???因?yàn)檫@些原因,vmalloc()僅在絕對(duì)必要時(shí)才會(huì)使用——典型的就是為了獲得大塊內(nèi)存時(shí),例如,當(dāng)模塊被動(dòng)態(tài)插入到內(nèi)核中時(shí),就把模塊裝載到由vmalloc()分配的內(nèi)存上。
總結(jié)
以上是生活随笔為你收集整理的kmalloc, vmalloc分配的内存结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于情感词典的python情感分析
- 下一篇: 开源 java CMS - FreeCM