一、kmalloc、vmalloc、malloc
malloc: 负责分配用户空间内存。malloc是标准的C库函数,在标准C库中,提供了malloc/free函数分配释放内存,这两个函数底层是由sark、brk、mmap、munmap这些系统调用实现的。
kmalloc:负责分配内核空间内存。用于申请较小的、连续的物理内存。以字节为单位进行分配,在<linux/slab.h>中,内存由于是线性映射,所以使用kmalloc分配内存是十分高效的。内存只有在要被DMA访问的时候才需要物理上连续。
vmalloc:负责分配内核空间内存。用于申请较大的内存空间,虚拟内存是连续的,以字节为单位进行分配,在<linux/vmalloc.h>中,vmalloc并不是简单的线性映射,它获取的内存并不是连续的,其转换逻辑比较复杂,分配速度上,自然vmalloc比kmalloc要慢。
另外还有几点值得一提:
1)寄存器是通过ioremap向vmalloc映射区去映射的,一旦调用ioremap,Linux就从vmalloc映射区找一个空闲的虚拟地址空间,然后去修改进程的页表,把这个虚拟地址往这个寄存器的物理地址去指。所以vmalloc映射区,除了vmalloc函数分配的内存会映射在该区域,设备的寄存器也同样会通过ioremap映射到该区域。
2)malloc、vmalloc申请内存后需要修改页表,而kmalloc申请内存时由于已经做了开机线性映射,所以不需要修改页表。
3)一般情况下在驱动程序中都是调用kmalloc()来给数据结构分配内存,而vmalloc()用在为活动的交换区分配数据结构,为某些I/O驱动程序分配缓冲区,或为模块分配空间。
二、常用函数总结:
用户空间:
API名称 | 是否物理连续 | 大小限制 | 单位 | 场景 |
---|---|---|---|---|
malloc/calloc/realloc/free | 不保证 | 堆申请 | 字节 | calloc初始化为0;realloc改变内存大小。 |
alloca | 栈申请 | 字节 | 向栈申请内存 | |
mmap/munmap | 将文件利用虚拟内存技术映射到内存中去。 | |||
brk、sbrk | 虚拟内存到内存的映射。sbrk(0)返回program break地址,sbrk调整对的大小。 |
内核空间:
API名称 | 是否物理连续 | 大小限制 | 单位 | 场景 |
---|---|---|---|---|
vmalloc/vfree | 虚拟连续 物理不定 | vmalloc区大小限制 | 页VMALLOC区域 | 可能睡眠,不能从中断上下文中调用,或其他不允许阻塞情况下调用。VMALLOC区域vmalloc_start~vmalloc_end之间,vmalloc比kmalloc慢,适用于分配大内存。 |
- 内核空间的slab:
API名称 | 是否物理连续 | 大小限制 | 单位 | 场景 |
---|---|---|---|---|
kmalloc/kcalloc/krealloc/kfree | 物理连续 | 64B-4MB (随slab而变) | 2^order字 Normal区域 | 大小有限,不如vmalloc/malloc大。最大/小值由KMALLOC_MIN_SIZE/KMALLOC_SHIFT_MAX,对应64B/4MB。从/proc/slabinfo中的kmalloc-xxxx中分配,建立在kmem_cache_create基础之上。 |
kmem_cache_create | 物理连续 | 64B-4MB | 字节大小,需对齐 Normal区域 | 便于固定大小数据的频繁分配和释放,分配时从缓存池中获取地址,释放时也不一定真正释放内存。通过slab进行管理。 |
- 内核空间的buddy:
API名称 | 是否物理连续 | 大小限制 | 单位 | 场景 |
---|---|---|---|---|
__get_free_page/__get_free_pages | 物理连续 | 4MB(1024页) | 页 Normal区 | __get_free_pages基于alloc_pages,但是限定不能使用HIGHMEM。 |
alloc_page/alloc_pages/free_pages | 物理连续 | 4MB | 页 Normal/Vmalloc都可 | CONFIG_FORCE_MAX_ZONEORDER定义了最大页面数2^11,一次能分配到的最大页面数是1024。 |
参考:
http://www.cnblogs.com/wuchanming/p/4465155.html
http://www.cnblogs.com/arnoldlu/p/8251333.html