内核的genalloc是给一些需要自己维护内存分配的内核模块使用的,如SRAM, TCM, Shared-memory,ION等,内存可以通过预留,或者从伙伴系统分配,然后添加到memory pool。
它提供了最先适配 fist-fit和最佳匹配 best-fit两种分配算法。
irst-fit 和 best-fit
这两种都是通过Bitmap来标记内存中每个分配单元的状态,空闲或已分配。 最先分配是将第一个可容纳请求大小的的连续空闲空间分配出去。 最佳分配是将可容纳请求大小的的最小连续空闲空间分配出去。 假设某片内存被划分为10个最小单 元.
这两种方法都会产生内存碎片,特别是first-fit,但是分配和释放都非常高效,实现也简单,没有buddy system那么复杂,不用考虑内存的回收,规整等等.
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);
3.使用方法
1. 创建内存池
//min_alloc_order最小分配单位
struct gen_pool *gen_pool_create(int min_alloc_order, int nid)
2. 添加内存到内存池
//内存来源可以是预留,也可以从伙伴系统分配.
int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phys,
size_t size, int nid)
3. 分配/释放内存
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)
4.销毁内存池
void gen_pool_destroy(struct gen_pool *pool)