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到vmallocNORETRY标记避免了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

9. 参考资料

  1. Linux内核地址空间的内存分布及分配_abc3240660的博客-CSDN博客_内核地址空间
  2. 宋宝华: kvmalloc ——倚天剑屠龙刀两大神器合体?_宋宝华的博客-CSDN博客