一种简单定长管理的内存池实现

痞子三分冷 提交于 2020-02-13 08:18:43

借鉴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了)。

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!