genalloc 是 linux 内核提供的通用内存分配器,源码位于 lib/genalloc.c。这个分配器为独立于内核以外的内存块提供分配方法,采用的是最先适配原则,android 最新的ION 内存管理器对 ION_HEAP_TYPE_CARVEOUT 类型的内存就是采用的这个分配器。
1、基础数据结构
首先看下分配器用到的几个数据结构,struct gen_pool 用来描述一个内存池:
struct gen_pool {
rwlock_t lock; /* 链表读写锁 */
struct list_head chunks; /* 内存池中内存块的链表 */
int min_alloc_order; /* 内存池最小分配单元的阶数,大小为 2^min_alloc_order */
};
在使用的时候需要向内存池中加入内存块,一个内存块即一大块连续的物理内存,用
struct gen_pool_chunk 来描述:
struct gen_pool_chunk {
spinlock_t lock; /* 操作内存块时用到的自旋锁 */
struct list_head next_chunk; /* 加入内存池的节点 */
unsigned long start_addr; /* 内存块的起始地址 */
unsigned long end_addr; /* 内存块的结束地址 */
unsigned long bits[0]; /* 内存块的位图 */
};
2、函数接口及调用方法
genalloc 用到的函数接口有下面几个:
/* 创建一个内存池,主要工作是完成 struct gen_pool 的初始化 */
struct gen_pool *gen_pool_create(int min_alloc_order, int nid);
/* 向内存池中加入内存块,addr 为起始地址,size 为大小 */
int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, int nid);
/* 销毁一个内存池 */
void gen_pool_destroy(struct gen_pool *pool);
/* 内存池分配内存的函数 */
unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size);
/* 内存池释放内存的函数 */
void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size);
对通用内存分配器的一般使用方法如下: