池式组件(2)固定大小内存块的内存池

一、定义

        内存池是一种内存分配方式,也被称为固定大小区块规划。内存池是在真正使用内存之前,先申请分配一定数量的、大小相等的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。

优点

  1. 性能提升:由于内存池中的内存块是预先分配好的,因此可以快速响应内存分配请求,避免了动态内存分配时的系统调用开销。
  2. 减少内存碎片:当进程长期运行malloc和free进行内存的分配与销毁时,因为是随机进行的,会产生内存碎片。而内存池中的内存块是预先分配和设置好的,因此不会产生内存碎片。
  3. 内存泄漏预防:由于内存池的使用是成块管理,可以在程序退出时一次性释放全部内存,从而避免了内存泄漏的风险。

二、固定大小内存块的内存池

        首先为内存池分配一大块内存块,并将其划分为多个固定大小的小块内存。每个小块内存的头部存储下一个小块内存的地址。

内存池结构体为:

typedef struct mempool_s{
	char *mem;
	char *free_ptr;
	int blocksize;
	int freecount;
}mempool_t;

mem指向内存池的起始位置。

free_ptr指向空内存块的起始位置。

blocksize为内存池的大小。

freecount为空内存块的数量。

创建内存池

int memp_create(mempool_t *m, int block_size){
//如果结构体不存在,返回错误值
	if(!m)return -1;
//内存块的大小
	m->blocksize = block_size;
//空闲内存块的数量
	m->freecount = MEM_PAGE_SIZE / block_size;
//创建预先设定好内存池大小
	m->mem = (char *)malloc(MEM_PAGE_SIZE);
//创建失败
	if(!m->mem){
		return -2;
	}
	memset(m->mem, 0, MEM_PAGE_SIZE);
//空闲内存块的地址
	m->free_ptr = m->mem;

	int i = 0;
	char *ptr = m->mem;
//为每个内存块前面4或者8个字节设置为下一个内存块的地址(32位系统指针大小为4,64位系统指针大小为8)
	for(i=0; i < m->freecount; i++){
		*(char **)ptr = ptr + block_size;
		ptr = ptr + block_size;
	}
//最后一个内存块指向空
	*(char **)ptr = NULL;
	
	return 0;
}

销毁内存池

void memp_destory(mempool_t *m) {

	if (!m) return ;

	free(m->mem);

}

由于这块内存在物理上是连续的,因此只需要释放内存池的基地址这阵就可以释放整块内存,无需逐个释放内存块。

分配内存块

void memp_alloc(mempool_t *m){
//如果内存池不存在或者没有空闲的内存块
	if(!m || m->freecount == 0) return NULL;
//取出第一个空闲的内存块
	void *ptr = m->free_ptr;
//取出空闲内存块指向的下一个内存块,并将其设置为当前空闲内存块
	m->free_ptr = *(char **)ptr;
//空闲内存块数量减一
	m->freecount --;
//返回内存块
	return ptr;
}

销毁内存块

void memp_free(mempool_t *m, void *ptr){
//将要释放的内存块头部指向空内存块
	*(char **)ptr = m->free_ptr;
//将空内存块指针指向释放的内存块
	m->free_ptr = (char *)ptr;

	m->freecount ++;
}

https://github.com/0voice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值