c语言手撕内存池组件

内存池是什么?

        内存池(Memory Pool)是一种内存管理技术,它预先分配一大块内存,然后将其分成多个固定大小的小块。这些小块被组织起来,用于程序在运行期间频繁进行的内存分配和释放操作。内存池通过创建一个“池子”来管理这些小块,以便在需要时快速分配和回收内存,而不需要每次都调用系统的内存分配函数(如 malloc()free())。

        内存池的基本概念是分配一次,重复使用。通过预先分配一大块内存,程序可以在需要时从这个预先分配的内存中快速获取内存块,并在不使用时归还给池子,从而减少频繁的分配和释放操作。
 

使用内存池有什么好处?

  1. 提高性能

            系统的内存分配函数(如 malloc() 和 free())在操作系统级别会涉及复杂的管理操作,尤其是在高频率分配和释放内存时,开销可能很大。
            内存池通过提前分配和复用内存块,减少了频繁的系统调用,从而显著提高性能。特别是在实时系统或需要处理大量小对象的系统中,内存池的性能提升尤为显著。 
  2. 减少内存碎片

            当使用系统的内存分配函数时,如果程序频繁分配和释放不同大小的内存块,可能会导致内存碎片化,即分散的小块可用内存,无法被有效利用。

            内存池通常管理的是大小固定的内存块,因此不会产生内存碎片问题。
  3. 防止内存泄漏

            在某些情况下,内存池可以帮助减少内存泄漏的风险。因为内存池的内存块是固定的,开发者不需要担心忘记释放特定的内存块,只需要在适当的时候释放整个内存池。

        在不同的业务场景下内存池通常也都不一样,在初学内存池阶段,我们实现一个固定块的内存池(在内存池里分配大小一样的小块)。下边是实现过程:

 

        如果释放某个内存块以后,我们下一个可以分配的内存块应该指向刚刚释放的那个内存块,问题是怎么找到它呢?可以通过二级指针实现链表,使每个小内存块的前边存放下一个可以分配的内存块的地址。

函数实现:



#include <stdio.h>
#include <stdlib.h>

// 8K的大小
#define MEM_PAGE_SIZE		8192

typedef struct mempool_s {
    int block_size;//固定小内存块的大小
    int free_count;//内存池中还能分配的内存块的数量 剩余还有多少块

    char *free_ptr;//下一个内存块可以分配的地址
    char *mem;//指向分配的内存池的起始地址  指向整块内存
} mempool_t;

//内存池初始化
int mp_init(mempool_t *m, int size) {

	if (!m) return -1;
	if (size < 16) size = 16;

	m->block_size = size;

        m->mem = (char *)malloc(MEM_PAGE_SIZE);//分配整块内存
	if (!m->mem) return -1;
	m->free_ptr = m->mem;
        m->free_count = MEM_PAGE_SIZE / size; //能够分配固定快的大小

	int i = 0;
        //二级指针实现单项链表
	char *ptr = m->free_ptr;
	for (i = 0;i < m->free_count;i ++) {
		*(char **)ptr = ptr + size;
		ptr += size;
	}
	*(char **)ptr = NULL;

	return 0;
}

//内存池销毁
void mp_dest(mempool_t *m) {
	if (!m || !m->mem) return ;
	
	free(m->mem);

}


//分配
void *mp_alloc(mempool_t *m) {

	if (!m || m->free_count == 0) return NULL;

	void *ptr = m->free_ptr;

	m->free_ptr = *(char **)ptr;
	m->free_count --;
	
	return ptr;
}

//释放
void mp_free(mempool_t *m, void *ptr) {

	*(char **)ptr = m->free_ptr;
	m->free_ptr = (char *)ptr;
	m->free_count ++;
}


int main() {

	mempool_t m;

        //分配大小为64字节的固定块
        mp_init(&m, 64);

	void *p1 = mp_alloc(&m);
	printf("1: mp_alloc: %p\n", p1);

	void *p2 = mp_alloc(&m);
	printf("2: mp_alloc: %p\n", p2);

	void *p3 = mp_alloc(&m);
	printf("3: mp_alloc: %p\n", p3);

	void *p4 = mp_alloc(&m);
	printf("4: mp_alloc: %p\n", p4);

	mp_free(&m, p2);

	void *p5 = mp_alloc(&m);
	printf("5: mp_alloc: %p\n", p5);
	

	return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值