一、简介:
内存分配的接口有很多,不同的申请函数有不同的功能,下面会做详细的介绍和对比。
- kmalloc:基于slab分配器,用于分配小内存,物理空间连续的内存块;
- vmalloc:用于分配大内存,虚拟地址连续的内存;
- malloc:为用户空间分配进程地址空间(即分配一块VMA);
- mmap:用户空间分配内存、读写大文件和加载静态库等;
可以用下图清晰的表明:
二、详细说明:
1、kmalloc(size_t size, gfp_t flags):
(1)kmalloc基于slub分配器,分配物理地址连续的小内存;
(2)gfp_mask常用标志:
- 进程上下文,可以睡眠 GFP_KERNEL
- 进程上下文,不可以睡眠 GFP_ATOMIC
- 中断处理程序 GFP_ATOMIC
- 软中断 GFP_ATOMIC
- Tasklet GFP_ATOMIC
- 用于DMA的内存,可以睡眠 GFP_DMA | GFP_KERNEL
- 用于DMA的内存,不可以睡眠 GFP_DMA | GFP_ATOMIC
(3)kfree(const void *ptr)
释放由kmalloc()分配出来的内存块;
2、vmalloc(unsigned long size):
(1)vmalloc 用于分配内核空间里连续虚拟地址的大内存块,分配的大小要以页面大小对齐(4Kb);
(2)vmalloc的函数如下:
void *vmalloc(unsigned long size)
{
return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
}
vmalloc -> __vmalloc ->__vmalloc_node
static void *__vmalloc_node(unsigned long size, unsigned long align,
gfp_t gfp_mask, pgprot_t prot,
int node, const void *caller)
{
return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
gfp_mask, prot, 0, node, caller);
}
以上GFP_KERNEL | __GFP_HIGHMEM说明有效从High memory区域开始分配,分配的区域在
VMALLOC_START -VMALLOC_END之间,关于vmalloc的区域看查看内存管理五中查看。
(3)void vfree(void *addr)
用于释放vmalloc申请的内存,这个函数可以睡眠,因此不能从中断上下文调用。
3、void *malloc(size_t size):
(1)malloc是用户空间用户分配内存的接口;
(2)malloc分配函数分配空间分如下两种情况:
testA通过malloc申请100Byte的内存时,其实是为用户空间分配进程地址空间(分配一块VMA),
在使用到buf的空间时,CPU才会触发缺页中断,在缺页中断中一页一页的分配物理内存;
testB在申请内存时,申请的虚拟内存都已经分配了物理内存并建立了页表映射;
void testA(void)
{
char *bufA = malloc(100);
* bufA = 100;
}
void testB(void)
{
char *bufB = malloc(100);
mlock(buf, 100);
}
(3)malloc对于用户空间的使用非常简单,但在内核空间会经过很多的处理,下面引用一张图可以清晰的表明:
4、void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset):
(1)mmap/munmap是用户空间常用的系统调用接口,用于用户程序分配内存、读写大文件、链接
动态库文件等;
(2)prot参数表示映射页面的读写权限:
- PROT_EXEC //页内容可以被执行
- PROT_READ //页内容可以被读取
- PROT_WRITE //页可以被写入
- PROT_NONE //页不可访问
(3)flags参数:指定映射对象的类型,映射选项和映射页是否可以共享。
作者:frank_zyp
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文无所谓版权,欢迎转载。