1. 总览
如下为内核开发或驱动开发常见的内存管理API关系,其他如CMA分配器等相关API未列出。
1.1. 框架图
1.2. 函数图总览
2. memblock分配器
memblock
分配器主要用于Linux启动时的内存分配,被memblock_alloc
分配后未被释放的内存,不会被加入到页管理器中。
api | param | desc |
---|---|---|
memblock_alloc | size, align | size表示要申请的大小,align表示内存对齐大小 |
3. 页分配器
页分配器相关的函数或宏在include/linux/gfp.h
中声明。常用的函数如下:
return | api | param |
---|---|---|
unsigned long | __get_free_pages | gfp_mask, order |
unsigned long | __get_free_page | gfp_mask |
unsigned long | __get_dma_pages | gfp_mask, order |
unsigned long | get_zeroed_page | gfp_mask |
struct page * | alloc_page | gfp_mask |
struct page * | alloc_pages | gfp_mask, order |
void | free_page | addr |
void | free_pages | addr, order |
void | __free_page | struct page * |
void | __free_pages | struct page *, order |
4. slab分区器
api | |
---|---|
kmem_cache_create | |
KMEM_CACHE | kmem_cache_create的封装 |
kmem_cache_create_usercopy | |
KMEM_CACHE_USERCOPY | kmem_cache_create_usercopy的封装 |
kmem_cache_alloc | |
kmem_cache_zalloc | |
kmem_cache_free | |
kmem_cache_destroy | |
kmem_cache_shrink | Shrink a cache |
kmem_cache_size |
5. kmalloc
kmalloc
只能分配几个固定大小的内存,申请值不在这些固定值之内时,会按向上对齐的原则,分配最接近申请值的内存块。
kmalloc
会根据申请的内存来决定来决定使用块分配器(slab/slub/slob)或页分配器进行内存分配。
api | |
---|---|
kmalloc | 申请连续的物理内存 |
kzmalloc | 申请连续的物理内存,并对申请的内存清零 |
kcalloc | 为多个对象申请连续的物理内存,并对申请的内存清零,内部调用kmalloc_array |
kmalloc_array | 为数组申请连续的物理内存 |
krealloc | 重新分配内存 |
kfree | 释放内存 |
kfree_sensitive | 释放内存前,将要释放的内存区域清零 |
ksize | 返回所分配的对象的实际内存的大小,不一定与kmalloc或kmem_cache_alloc传入值一致 |
kstrdup | 根据给定字符串申请内存,并完成字符串拷贝 |
6. vmalloc
vmalloc
原理是分配多个物理页面(不保证物理地址连续),然后将页面映射到连续的虚拟地址。所以vmalloc
分配的粒度为页面大小,最终也会按页面大小进行对齐。
6.1. vmalloc
api | |
---|---|
__vmalloc | 低级vmalloc函数,由其他api调用 |
vmalloc | allocate virtually contiguous memory |
vmalloc_node | allocate memory on a specific node |
vmalloc_user | allocate zeroed virtually contiguous memory for userspace |
vmalloc_huge | allocate virtually contiguous memory, allow huge pages |
vmalloc_32 | allocate virtually contiguous memory (32bit addressable) |
vmalloc_32_user | allocate zeroed virtually contiguous 32bit memory |
vzalloc | allocate virtually contiguous memory with zero fill |
vzalloc_node | allocate memory on a specific node with zero fill |
vfree | |
vfree_atomic | This one is just like vfree() but can be called in any atomic context except NMIs |
6.2. vmap
api | |
---|---|
vmap | map an array of pages into virtually contiguous space |
vmap_pfn | map an array of PFNs into virtually contiguous space |
vunmap | |
vm_map_ram | map pages linearly into kernel virtual address (vmalloc space) |
vm_unmap_ram |
7. kvmalloc
逻辑上是,大于一页的时候用vmalloc()
,小于等于1页用kmalloc()
。
而kvmalloc()
的实现代码里面则对类似逻辑进行了非常智能地处理。
大于一个page的时候,会先用kmalloc()
进行__GFP_NORETRY
的尝试,如果尝试失败就fallback到vmalloc
(NORETRY
标记避免了kmalloc
在申请内存失败地情况下,反复尝试甚至做OOM来获得内存)。
当然,kvmalloc()
的size如果小于1个page,则沿用kmalloc()
逻辑,而且也不会设置__GFP_NORETRY
,如果反复尝试失败的话,也不会fallback到vmalloc()
,因为vmalloc()
申请小于1个page的内存是不合适的。
api | |
---|---|
kvmalloc | 根据申请内存大小自动决定使用kmalloc或vmalloc |
kvzalloc | 内存申请成功后将其清零 |
kvcalloc | 为多个对象申请内存,并将申请到的内存清零,内部调用kvmalloc_array |
kvmalloc_array | 为数组申请内存 |
kvfree | 释放申请到的内存 |
kvfree_sensitive | 是否内存前对内存区域进行清零,与kvfree不同的是,kvfree_sensitive需要指定长度 |
is_vmalloc_addr | 判断指针是否处于vmalloc区域 |
8. devm
devm
的作用是自动释放申请的资源,无需再手动释放。
8.1. memory allocation
api |
---|
devm_kmalloc |
devm_kzalloc |
devm_kcalloc |
devm_krealloc |
devm_kmalloc_array |
devm_get_free_pages |
devm_free_pages |
devm_alloc_percpu |
devm_free_percpu |
devm_kasprintf |
devm_kstrdup |
devm_kstrdup_const |
devm_kmemdup |
8.2. ioremap
api | desc |
---|---|
devm_ioremap_resource | check, request region, and ioremap resource |
devm_ioremap_resource_wc | write-combined variant of devm_ioremap_resource() |
devm_of_iomap | Requests a resource and maps the memory mapped IO for a given device_node managed by a given device |