概要

所谓内存池,顾名思义和线程池的设计原理是一样的,为了减少频繁申请释放内存而带来的资源消耗,减少释放内存后产生的内存碎片。

设计理念

为了方便管理内存池的设计通常是划分出一定数量的内存块,这些内存块的长度是一样的; 用户申请内存块时返回空闲的内存块地址,如果内存块使用完毕就释放该内存块,将该内存块置为空闲状态,放回到内存池,供以后使用。

内存池的设计核心几大模块:创建内存池,申请内存块,释放内存块,销毁内存池!

当然这只是常用的内存池设计,实际项目中可以根据需求设计不同的线程池:内存块的长度不一,可以提供自定义的内存块设计等兼容性更高的内存池。

本文只做内存池原理的讲解和实现最基础的内存池!更多的功能根据实际的需求进行扩展即可。

内存池的设计思路有很多,可以给予链表,数组,队列等进行设计,核心就是怎么存储内存块信息;本期是基于链表进行的内存池设计。

模块设计

内存池结构

内存块节点结构

typedef structMemoryBlock{void *data;//内存块起始地址
    struct MemoryBlock *next;//下一个内存块的地址
}MemoryBlock;

内存池结构

typedef structMemoryPool{
MemoryBlock
*freeList;//空闲内存块链表 MemoryBlock *usedList;//占用内存块链表 int freeCount;//空闲内存块数量 int usedCount;//占用内存块数量 int blockCount;//内存块总数量 }MemoryPool;

创建内存池

通过参数确定内存池中内存块的大小和数量,然后给每个内存块开辟空间,然后初始化空闲链表,占用链表,空闲数量,占用数量等

MemoryPool *InitMemoryPool(int blockSize, intblockCount)
{
MemoryPool
*pool =NULL;


pool
= (MemoryPool *)malloc(sizeof(MemoryPool));//为内存池分配空间 pool->freeList =NULL;
pool
->usedList =NULL;for(int i = 0; i < blockCount; i++)
{
//创建内存块节点,插入到空闲链表 MemoryBlock * block = (MemoryBlock *)malloc(sizeof(MemoryBlock));
block
->data = malloc(blockSize);
block
->next = pool->freeList;
pool
->freeList =block;
}
//初始化状态 pool->freeCount =blockCount;
pool
->usedList = 0;
pool
->blockCount =blockCount;returnpool;
}

申请内存块

将内存池中空闲的内存块提供给用户使用,如果没有空闲内存块返回NULL。

void *AllocateBlock(MemoryPool *pool)
{
if(pool->freeList == NULL || pool->freeCount == 0)returnNULL;
MemoryBlock
*node = pool->freeList;//该内存块从空闲链表删除 pool->freeList = node->next;//该内存块插入到占用链表 node->next = pool->usedList;
pool
->usedList =node;//更新空闲,占用状态 pool->usedCount++;
pool
->freeCount--;return node->data;
}

释放内存块

将内存块放回到内存池

void FreeBlock(MemoryPool *pool, void *data)
{
MemoryBlock
*cur = pool->usedList;
MemoryBlock
*pre =NULL;//寻找给内存块的节点 while(pre != NULL && cur->data !=data)
{
pre
=cur;
cur
= cur->next;
}
if(cur ==NULL)return;//将该内存块从占用链表删除 if(pre !=NULL)
pre
->next = cur->next;elsepool->usedList = cur->next;//将该内存块插入到空闲链表 cur->next = pool->freeList;
pool
->freeList =cur;

pool
->freeCount++;
pool
->usedCount--;return;
}

销毁内存池

销毁所有的内存块及分配过的空间

void DestroyMemoryPool(MemoryPool *pool)
{
MemoryBlock
*pre =NULL;//释放所有空闲内存块空间 while(pool->freeList !=NULL)
{
pre
= pool->freeList;free(pool->freeList->data);
pool
->freeList = pool->freeList->next;free(pre);
}
//释放所有占用内存块空间 while(pool->usedList !=NULL)
{
pre
= pool->usedList;free(pool->usedList->data);
pool
->usedList = pool->usedList->next;free(pre);
}
//释放内存池空间 free(pool);

pool
->freeList =NULL;
pool
->usedList =NULL;
pool
->freeCount = 0;
pool
->usedCount = 0;return;
}

至此一个最基础的内存池算是已经完成,在实际项目中可以在此基础上进行扩展;

main函数调用

int main(void)
{
MemoryPool
*pool;

pool
= InitMemoryPool(10, 5);int *str = (int *)AllocateBlock(pool);*str = 2;int *ptr = (int *)AllocateBlock(pool);*ptr = 3;
printf(
"free block : %d, used block : %d\n", pool->freeCount, pool->usedCount);
FreeBlock(pool, ptr);
printf(
"free block : %d, used block : %d\n", pool->freeCount, pool->usedCount);

DestroyMemoryPool(pool);
return 0;
}

标签: none

添加新评论