内存池实现二

一、实现目的:

1.实现不定长大块,可以分配更大的内存,结构如下:第一个位置max用于判断需要分配的内存大小,大于max使用大块,小于max使用小块;第二个位置指针指向小块的首地址;第三个位置指针指向大块首地址。

2.大块结构如下,使用队列结构,左边指针指向下一个大块首地址,右边指向分配的内存。

3.下图是对应结构的代码,小块中last为起始地址,end指向已使用内存位置,next指向未使用内存末位置。

二、数据结构设计

1.这个结构用于检测创建内存的大小选择小块还是大块,存储大小块的首地址。

typedef struct mp_pool_s{
    size_t max;
    struct mp_node_s *head;
    struct mp_large_s *large;
}mp_pool_t;

2.小块结构:当申请的内存的小于max时使用小块。

typedef struct mp_node_s{
    unsigned char *last;
    unsigned char * end;
    struct mp_node_s *next;
}mp_node_t;

3.大块结构:当申请的内存大于max时使用大块。

typedef struct mp_large_s{
    struct mp_large_s *next;
    void *alloc;
}mp_large_t;

三、内存池接口设计

1.创建内存池:对pool池中小块和大块初始化

int mp_create(mp_pool_t *pool, size_t size){
    if(!pool || size < 0) return -1;

    void *mem = malloc(size);

    struct mp_node_s *node = (struct mp_node_s *)mem;
    node->last = (char*)mem + sizeof(struct mp_node_s);
    node->end = (char *)mem + size;
    node->next = NULL;

    pool->head = node;
    pool->max = size;
    pool->large = NULL;

    return 0;
}

2.销毁内存池:释放大块队列中分配的内存,指针指向NULL,释放小块分配的内存。

void mp_destroy(mp_pool_t* pool){
    mp_large_t* l;
    
    for(l = pool->large; l; l = l->next){
        if(l->alloc){
            free(l->alloc);
        }
    }
    pool->large = NULL;

    mp_node_t *node = pool->head;
    while(!node){
        mp_node_t *tmp = node->next;
        free(node);
        node = tmp;
    }
}

3.内存池分配内存:首先检测需要分配的内存大小,大于max时使用大块分配,循环遍历当前池中的大块队列中是否有空余的位置,如果存在则使用队列中空余位置分配内存;不存在使用头插法或者尾插法插入到大块队列中。

static void *mp_alloc_block(mp_pool_t *pool, size_t size){

    void *mem = malloc(size);
    struct mp_node_s *node = (struct mp_node_s *)mem;
    node->last = (char *)mem + sizeof(struct mp_node_s);
    node->end = (char *)mem + size;
    node->next = NULL;

    void *ptr = node->last;
    node->last += size;

    mp_node_t *iter = pool->head;
    while(iter->next != NULL){
        iter = iter->next;
    }
    iter->next = node;

    return ptr;
}

static void *mp_alloc_large(mp_pool_t* pool, size_t size){
    if(!pool)return NULL;

    printf("large block: %d\n", size);
    void *ptr = malloc(size);
    if(ptr == NULL)return NULL;

    mp_large_t *l;
    for(l = pool->large; l; l->alloc){
        if(l->alloc == NULL){
            l->alloc = ptr;
            return ptr;
        }
    }

    l = mp_alloc(pool, sizeof(mp_large_t));
    if(l == NULL){
        free(ptr);
        return NULL;
    }
    l->alloc = ptr;

    l->next = pool->large;
    pool->large = 1;

    return ptr;
}

void *mp_alloc(mp_pool_t* pool, size_t size){
    if(size > pool->max){
        return mp_alloc_large(pool, size);
    }

    void *ptr = NULL;

    mp_node_t *node = pool->head;

    do{
        if(node->end-node->last < size){
            ptr = node->last;
            node->last += size;

            return ptr;
        }
        node = node->next;
    }while(node);

    return mp_alloc_block(pool, size);
}

4.对分配的内存块进行释放:

void mp_free(mp_pool_t *pool, void *ptr){
    mp_large_t *l;

    for(l = pool->large; l; l = l->next){
        if(l->alloc == ptr){
            free(l->alloc);
            l->alloc == NULL;
            return;
        }
    }
}

分享一个学习链接,有学习需要的同学可以看一下:

https://xxetb.xetslk.com/s/3yNycZ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值