内存池的简单实现c语言-创新互联

内存池

内存池是为了解决大量malloc,free,导致的某些内存碎片。统一管理起来,比较方便。
基本思想是,根据要分配的内存,分为大块内存和小块内存。

创新互联是一家专业提供深州企业网站建设,专注与成都网站建设、成都网站设计HTML5、小程序制作等业务。10年已为深州众多企业、政府机构等服务。创新互联专业的建站公司优惠进行中。
  1. 大块内存直接用链表管理。
  2. 小块内存,我这里设置为4k大小,内部再用一个一个小节点链表。
    大概的数据结构如下:
    在这里插入图片描述
1.核心的数据结构
  1. 小片内存(4k以内)节点,第一个成员last, 是当前节点的首地址,end是指该4k内存的最后一段地址。

    struct  mp_node_s{unsigned char *last; //当前节点的位置
        unsigned char *end; //当前分配的内存(小于等于4k)最后一位
        struct mp_node_s *next;//指向下一个节点
        size_t failed=0;//失败次数
    };
  2. 大片内存:

    struct mp_large_s{struct mp_large_s *next;//下个节点
        void *alloc;//分配的内存
    
    };
  3. 池节点:其其核心思想就是将分配的内存组织起来

    struct mp_pool_s {struct mp_large_s *large;
        struct mp_node_s *head;
        struct mp_node_s *current; //指向当前的节点
    
        int max;
    };
2. 流程
  1. 创建池,先创建出一个32位对齐的内存块,这个内存块是size大小,再加上mp_pool_s这个结构体的本身大小.
    在这里插入图片描述

    #define MP_ALIGNMENT       		32
    #define MP_PAGE_SIZE			4096
    #define MP_MAX_ALLOC_FROM_POOL	(MP_PAGE_SIZE-1)
    
    struct mp_pool_s *mp_create_pool(size_t size) {struct mp_pool_s *p;
    	int ret = posix_memalign((void **)&p, MP_ALIGNMENT, size + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s));
    	if (ret) {return NULL;
    	}
    	
    	p->max = (size< MP_MAX_ALLOC_FROM_POOL) ? size : MP_MAX_ALLOC_FROM_POOL;//小与4k,就用原本的大小,大于4k,那么限制为4k-1
    	p->current = p->head; //将当前结点指向池的头部
    	p->large = NULL;
    
    	p->head->last = (unsigned char *)p + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s); //当前头部
    	p->head->end = p->head->last + size;
    
    	p->head->failed = 0;
    
    	return p;
    
    }
  2. 分配内存函数,分为,①分配大块内存; ②分配小内存节点时,考虑两种情况,小内存块还够用,小内存块不够用了,得分配新的小内存块。

    void *mp_alloc(struct mp_pool_s *pool, size_t size) {unsigned char *m;
    	struct mp_node_s *p;
    //小于等于小内存块大小的
    	if (size<= pool->max) {//就在当前节点后分配内存
    		p = pool->current;
    //遍历当前节点后的节点,查找有没有适合大小的内存块
    		do {	
    			m = mp_align_ptr(p->last, MP_ALIGNMENT);
    	//分配范围,依然还在内存块范围的,就不新分配新块了,就地分配
    			if ((size_t)(p->end - m) >= size) {		p->last = m + size;
    				return m;
    			}
    			p = p->next;
    		} while (p);
    //没有合适大小的内存块,直接创建一块新小内存块
    		return mp_alloc_block(pool, size);
    	}
    //分配大块内存
    	return mp_alloc_large(pool, size);
    	
    }
  3. 新建一个≤4k的小内存块

在这里插入图片描述

#define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
#define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))

static void *mp_alloc_block(struct mp_pool_s *pool, size_t size) {

	unsigned char *m;//
	struct mp_node_s *h = pool->head; //头部的小内存节点
	size_t psize = (size_t)(h->end - (unsigned char *)h); //获取小内存块大小
	//为m分配出一个内存
	int ret = posix_memalign((void **)&m, MP_ALIGNMENT, psize); //先分配出一个“页”(<=4k)
	if (ret) return NULL;

	struct mp_node_s *p, *new_node, *current; 
	new_node = (struct mp_node_s*)m; //

	new_node->end = m + psize;
	new_node->next = NULL;
	new_node->failed = 0;
//在分配好的小内存块中,分配一块节点内存size
	m += sizeof(struct mp_node_s);
	m = mp_align_ptr(m, MP_ALIGNMENT);
	new_node->last = m + size; //last指向节点内存的末尾

	current = pool->current;
//遍历当前节点后的节点,如果有失败大于4次的节点,就把池的当前节点指向失败大于4次的节点
//4是一个经验值
	for (p = current; p->next; p = p->next) {
		if (p->failed++ >4) {
			current = p->next;
		}
	}
	p->next = new_node; //将最后一个结点的next指向新分配的内存块

	pool->current = current ? current : new_node; 

	return m;

}
```
  1. 创建大块内存,非常好理解,一个单链表,没什么好说的

    static void *mp_alloc_large(struct mp_pool_s *pool, size_t size) {void *p = malloc(size); //直接分配内存
    	if (p == NULL) return NULL;
    
    	size_t n = 0;
    	struct mp_large_s *large;
    	for (large = pool->large; large; large = large->next) {if (large->alloc == NULL) {	large->alloc = p;
    			return p;
    		}
    		if (n ++ >3) break;
    	}
    //large结构体本身也是存在小内存块里的
    	large = mp_alloc(pool, sizeof(struct mp_large_s));
    	if (large == NULL) {free(p);
    		return NULL;
    	}
    
    	large->alloc = p;
    	large->next = pool->large;
    	pool->large = large;
    
    	return p;
    }

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧

网站标题:内存池的简单实现c语言-创新互联
浏览地址:https://www.cdcxhl.com/article22/ccgjcc.html

成都网站建设公司_创新互联,为您提供营销型网站建设网站建设网站排名定制网站建站公司面包屑导航

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

成都网页设计公司