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


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

  • 相关阅读:
    Android和kernel杂散点集合
    Kernel的IIC驱动分析
    Uboot流程分析
    关于在eclipse当中,对接口方法的实现使用@Override报错的解决方式
    任务调度工具oozie和azkaban的对比
    实现Linux和windows之间实现文件传输的问题解决方式。sftp和ftp
    使用spring-boot创建定时任务。同时创建多线程执行定时任务。
    【C++11】新特性——auto的使用
    Inline函数使用注意事项
    结构体变量的sizeof计算
  • 原文地址:https://www.cnblogs.com/westfly/p/simplemempool.html
Copyright © 2020-2023  润新知