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