`
womendu
  • 浏览: 1479632 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

[转]kmalloc, vmalloc分配的内存结构

 
阅读更多

[转]kmalloc, vmalloc分配的内存结构

对于提供了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 <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
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("<1>pagemem addr=%x", pagemem);

 kmallocmem = (unsigned char*)kmalloc(100, 0);
 printk("<1>kmallocmem addr=%x", kmallocmem);

 vmallocmem = (unsigned char*)vmalloc(1000000);
 printk("<1>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()分配的内存上。


原文地址 http://blog.chinaunix.net/u/19782/showart_282318.html

分享到:
评论

相关推荐

    kmalloc()和vmalloc()的区别

    kmalloc()和vmalloc()的区别

    Linux内存管理之malloc、vmalloc、kmalloc

    Linux内存管理之malloc、vmalloc、kmalloc, 区别,相似之处

    memory_map_kmalloc.c

    vmalloc分配的内存虚拟地址连续但物理地址不连续,所以只能在缺页异常中逐页建立映射 下面给出使用kmalloc分配内存,并在mmap函数中一次性建立映射的示例

    Kmalloc 共享内存池技术架构详解-KaiwuDB

    本期内容主题为《 Kmalloc 共享内存池技术架构详解》,KaiwuDB 为优化内存池技术,将内存池分为多个 Heap,每个 Heap 使用不同的数据结构管理内存,在申请和释放内存时,允许多个进程访问同一块内存,使用并发访问...

    linux内存分配实例

    可见分配的内存的虚拟地址符合预期,__get_fre_page和kmalloc分配的内存在线性映射区,vmalloc分配的内存在非连续内存区

    kmalloc/kfree封装代码

    kmalloc/kfree内存管理函数封装代码。

    linux 内核 内存泄露检测

    linux 内核 内存泄露检测 linux 内核 内存泄露检测 linux 内核 内存泄露检测 linux 内核 内存泄露检测 linux 内核 内存泄露检测 linux 内核 内存泄露检测 linux 内核 内存泄露检测

    linux c内存分配函数介绍

    介绍linux c中的基本内存分配函数, 比如malloc, kmalloc, zalloc等等

    LINUX设备驱动第三版_588及代码.rar

    第八章 分配内存 kmalloc函数的内幕 后备高速缓存 get_free_page和相关函数 vmalloc及其辅助函数 per-CPU变量 获取大的缓冲区 快速参考 第九章 与硬件通信 I/O端口和I/O内存 使用I/O端口 I/O端口示例 ...

    ION基本概念.docx

    ION是Google的下一代内存管理器,用来支持不同的内存分配机制,如CARVOUT(PMEM),物理连续内存(kmalloc), 虚拟地址连续但物理不连续内存(vmalloc), IOMMU等。

    Linux 内存管理内幕

    Linux内存管理技术,详细讲解了kmalloc、page,以及buddy算法的相关知识,若是想了解Linux内核中的内存分配、释放,一致性细节,本文档将是不可多得的选择

    Linux DeviceDrivers 3rd Edition

    第八章 分配内存 213 kmalloc函数的内幕 213 后备高速缓存 217 get_free_page和相关函数 221 vmalloc及其辅助函数 225 per-CPU变量 228 获取大的缓冲区 230 快速参考 231 第九章 与硬件通信 235 I/O端口和I...

    嵌入式系统/ARM技术中的浅谈malloc与 kmalloc、cmalloc、realloc、new 的区别

    作者:陶宁,华清远见嵌入式... 作 用:calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小。  例 子:  3.realloc  作 用:重新分配内存空间。  例 子:

    linux设备驱动程序

    内容简介 《LINUX设备驱动程序(第3版)》已针对...第八章 分配内存 kmalloc函数的内幕 后备高速缓存 get—free—page和相关函数 vmalloc及其辅助函数 per-CPU变量 获取大的缓冲区 快速参考 ch09... ch10... ... ch18...

    嵌入式系统/ARM技术中的GPIO设备程序开发步骤

    GPIO驱动可以归类为Linux设备驱动的字符设备驱动,以下是开发它的一些具体步骤。... kmalloc()函数分配一段内存,这样就实现了Chrdevs向量表中指向设备驱动程序名称的指针。使用kfree释放内存。  

    Linux驱动_mmap1

    1.1 Linux内核常用的内存空间申请方式内核空间申请内存主要函数有:kmalloc(),__get_free_pages()他们申请的内存位于物理内存映射区

    os86:用于基本os开发的裸机沙箱

    实施: 多重启动分页和虚拟内存,具有高内存内核首次匹配kmalloc()和kfree()的简单堆分配简单的中断和异常简单协作多任务去做第三环,用户空间调度和抢先式多任务处理文件系统很多其他的东西移植到RISC-V并在...

    一个雏形的Unix-like内核開源代碼 適合初學者模仿調試~

    一个雏形的Unix-like内核。 37个系统调用,七千行C,二百多行汇编,在bochs之上。诚然还脱不去“玩具”的标签,不过也算完成了它的设计目标,那就是...一个简单的kmalloc()(可惜没大用上)。 一个简单的终端。 Syscalls

    linux完全教学手册

    linux教学手册,看了很少一部分,感兴趣的拿去看吧

Global site tag (gtag.js) - Google Analytics