借鉴ucos消息队列中的实现,对内存池只提供信息的管理头部,由用户管理内存的分配与释放。
借用了STL中的管理思路
typedef union object_t { union object_t *next; //下一个对象 char data[1]; }object_t;
注意其为union类型,next和data复用
typedef struct ares_block { size_t object_size; //单个对象的大小 size_t block_size; //占用的空间总数 size_t count; //剩余有多少个对象 object_t * free_list; //空闲的对象块 char *data; //实际指向缓冲区位置 struct list_head list_block;//多个内存块 }mem_block_t;
基本的管理块 mem_block_t的接口函数。
void memblock_init(mem_block_t *block,size_t object_size,size_t buf_len,char *data); void memblock_destroy(mem_block_t *block); char *memblock_alloc(mem_block_t *block,size_t object_size); void memblock_dealloc(mem_block_t *block,char *mem);
初始化后的结构为
用于管理mem_block_t 的内存池
typedef struct ares_pool { size_t pool_size; size_t free_mem; size_t total_size; object_t * use_list; //空闲的对象块; struct list_head block_list; //多个内存池 }mem_pool_t;
对应的接口函数为
void mempool_init(mem_pool_t *pool); void mempool_attach(mem_pool_t *pool,mem_block_t *block); void mempool_destroy(mem_pool_t *pool); char *mempool_alloc(mem_pool_t *pool,size_t object_size); void mempool_dealloc(mem_pool_t *pool,size_t object_size,char *mem);
初始化后的结构,只有一个mem_block_t
以上的结构,实现的思路为
一个memblock管理有篇内存区域,它被分割为n个,用单链表的形式组织起来
View Code
void memblock_init(mem_block_t *block,size_t object_size,size_t buf_len,char *data) { object_t *object = (object_t *)(data); block->free_list = object; while(++i < block->count) { data +=object_size; object->next = (object_t *)data; object = object->next; } object->next = 0; }
block分配的时候,从中取出一块小内存,从free_list中删除一个链表节点即可
memblock_alloc
char *memblock_alloc(mem_block_t *block,size_t object_size) { assert(block); object_t *object; assert(object_size == block->object_size); if(block->free_list) { object = block->free_list; block->free_list = object->next; --block->count; } return object?object->data:NULL; }
释放即将内存块插入到free_list中
memblock_dealloc
void memblock_dealloc(mem_block_t *block,char *mem) { object_t *object = (object_t *)mem; assert(block && object); if(block->free_list) { object->next = block->free_list; block->free_list = object; }else{ block->free_list = object; } ++block->count; }
以上的block的思路。
对于pool来说,基本上是转调block的接口函数。
在pool中,block是按照object_size递增组织的(将STL中的数组用list组织)
mempool_attach函数将一个block插入到相应的正确位置。
mempool_alloc按照object_size查找block,然后调用memblock_alloc分配内存。
同理mempool_dealloc类似。
总结
1.未考虑多线程的情况,这个需要在真实实现的时候加上互斥访问。
2.这种方式组织的内存池,不是通用的内存池,实现只为满足特定的需求。
3.内存池只提供信息头部来组织内存块,内存的分配与释放都由用户负责,用户可以预先建立几个经常使用的数据类型大小(或者如STL中,向上ROUND_UP多分配内存),
4.每次只能分配一个object_size大小的内存,对于分配多个的需求暂时不支持——扩展开来需要再添加一个信息头类似(类似于pbuf了)。