使用C語言實現(xiàn)內(nèi)存池的示例代碼
概要
所謂內(nèi)存池,顧名思義和線程池的設(shè)計原理是一樣的,為了減少頻繁申請釋放內(nèi)存而帶來的資源消耗,減少釋放內(nèi)存后產(chǎn)生的內(nèi)存碎片。
設(shè)計理念
為了方便管理內(nèi)存池的設(shè)計通常是劃分出一定數(shù)量的內(nèi)存塊,這些內(nèi)存塊的長度是一樣的; 用戶申請內(nèi)存塊時返回空閑的內(nèi)存塊地址,如果內(nèi)存塊使用完畢就釋放該內(nèi)存塊,將該內(nèi)存塊置為空閑狀態(tài),放回到內(nèi)存池,供以后使用。
內(nèi)存池的設(shè)計核心幾大模塊:創(chuàng)建內(nèi)存池,申請內(nèi)存塊,釋放內(nèi)存塊,銷毀內(nèi)存池!
當(dāng)然這只是常用的內(nèi)存池設(shè)計,實際項目中可以根據(jù)需求設(shè)計不同的線程池:內(nèi)存塊的長度不一,可以提供自定義的內(nèi)存塊設(shè)計等兼容性更高的內(nèi)存池。
本文只做內(nèi)存池原理的講解和實現(xiàn)最基礎(chǔ)的內(nèi)存池!更多的功能根據(jù)實際的需求進(jìn)行擴(kuò)展即可。
內(nèi)存池的設(shè)計思路有很多,可以給予鏈表,數(shù)組,隊列等進(jìn)行設(shè)計,核心就是怎么存儲內(nèi)存塊信息;本期是基于鏈表進(jìn)行的內(nèi)存池設(shè)計。
模塊設(shè)計
內(nèi)存池結(jié)構(gòu)
內(nèi)存塊節(jié)點結(jié)構(gòu)
typedef struct MemoryBlock{
void *data;//內(nèi)存塊起始地址
struct MemoryBlock *next;//下一個內(nèi)存塊的地址
}MemoryBlock;內(nèi)存池結(jié)構(gòu)
typedef struct MemoryPool{
MemoryBlock *freeList;//空閑內(nèi)存塊鏈表
MemoryBlock *usedList;//占用內(nèi)存塊鏈表
int freeCount;//空閑內(nèi)存塊數(shù)量
int usedCount;//占用內(nèi)存塊數(shù)量
int blockCount;//內(nèi)存塊總數(shù)量
}MemoryPool;創(chuàng)建內(nèi)存池
通過參數(shù)確定內(nèi)存池中內(nèi)存塊的大小和數(shù)量,然后給每個內(nèi)存塊開辟空間,然后初始化空閑鏈表,占用鏈表,空閑數(shù)量,占用數(shù)量等
MemoryPool *InitMemoryPool(int blockSize, int blockCount)
{
MemoryPool *pool = NULL;
pool = (MemoryPool *)malloc(sizeof(MemoryPool));//為內(nèi)存池分配空間
pool->freeList = NULL;
pool->usedList = NULL;
for(int i = 0; i < blockCount; i++)
{
//創(chuàng)建內(nèi)存塊節(jié)點,插入到空閑鏈表
MemoryBlock * block = (MemoryBlock *)malloc(sizeof(MemoryBlock));
block->data = malloc(blockSize);
block->next = pool->freeList;
pool->freeList = block;
}
//初始化狀態(tài)
pool->freeCount = blockCount;
pool->usedList = 0;
pool->blockCount = blockCount;
return pool;
}申請內(nèi)存塊
將內(nèi)存池中空閑的內(nèi)存塊提供給用戶使用,如果沒有空閑內(nèi)存塊返回NULL。
void *AllocateBlock(MemoryPool *pool)
{
if(pool->freeList == NULL || pool->freeCount == 0)
return NULL;
MemoryBlock *node = pool->freeList;
//該內(nèi)存塊從空閑鏈表刪除
pool->freeList = node->next;
//該內(nèi)存塊插入到占用鏈表
node->next = pool->usedList;
pool->usedList = node;
//更新空閑,占用狀態(tài)
pool->usedCount++;
pool->freeCount--;
return node->data;
}釋放內(nèi)存塊
將內(nèi)存塊放回到內(nèi)存池
void FreeBlock(MemoryPool *pool, void *data)
{
MemoryBlock *cur = pool->usedList;
MemoryBlock *pre = NULL;
//尋找給內(nèi)存塊的節(jié)點
while(pre != NULL && cur->data != data)
{
pre = cur;
cur = cur->next;
}
if(cur == NULL)
return;
//將該內(nèi)存塊從占用鏈表刪除
if(pre != NULL)
pre->next = cur->next;
else
pool->usedList = cur->next;
//將該內(nèi)存塊插入到空閑鏈表
cur->next = pool->freeList;
pool->freeList = cur;
pool->freeCount++;
pool->usedCount--;
return;
}銷毀內(nèi)存池
銷毀所有的內(nèi)存塊及分配過的空間
void DestroyMemoryPool(MemoryPool *pool)
{
MemoryBlock *pre = NULL;
//釋放所有空閑內(nèi)存塊空間
while(pool->freeList != NULL)
{
pre = pool->freeList;
free(pool->freeList->data);
pool->freeList = pool->freeList->next;
free(pre);
}
//釋放所有占用內(nèi)存塊空間
while(pool->usedList != NULL)
{
pre = pool->usedList;
free(pool->usedList->data);
pool->usedList = pool->usedList->next;
free(pre);
}
//釋放內(nèi)存池空間
free(pool);
pool->freeList = NULL;
pool->usedList = NULL;
pool->freeCount = 0;
pool->usedCount = 0;
return;
}至此一個最基礎(chǔ)的內(nèi)存池算是已經(jīng)完成,在實際項目中可以在此基礎(chǔ)上進(jìn)行擴(kuò)展;
main函數(shù)調(diào)用
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;
}到此這篇關(guān)于使用C語言實現(xiàn)內(nèi)存池的示例代碼的文章就介紹到這了,更多相關(guān)C語言實現(xiàn)內(nèi)存池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++中賦值運(yùn)算符與逗號運(yùn)算符的用法詳解
這篇文章主要介紹了C++中賦值運(yùn)算符與逗號運(yùn)算符的用法詳解,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-09-09
使用設(shè)計模式中的單例模式來實現(xiàn)C++的boost庫
這篇文章主要介紹了使用設(shè)計模式中的單例模式來實現(xiàn)C++的boost庫的方法,其中作者對線程安全格外強(qiáng)調(diào),需要的朋友可以參考下2016-03-03
C語言中帶頭雙向循環(huán)鏈表基本操作的實現(xiàn)詳解
無頭單向非循環(huán)鏈表結(jié)構(gòu)簡單,一般不會單獨用來存數(shù)據(jù)。而帶頭雙向循環(huán)鏈表的結(jié)構(gòu)較為復(fù)雜,一般用在單獨存儲數(shù)據(jù)。本文將介紹帶頭雙向循環(huán)鏈表的基本操作,需要的可以參考一下2022-11-11
搭建C語言開發(fā)環(huán)境(Windows平臺)匯總
本文給大家匯總了5種在WIN平臺下搭建C語言開發(fā)環(huán)境的方法,包括一、在Windows平臺配置GNU環(huán)境,二、使用Sublime Test開發(fā)C語言程序,三、使用VisualStudio開發(fā)C語言程序,四、搭建EclipseCDT集成開發(fā)環(huán)境,五、搭建Clion集成開發(fā)環(huán)境,有需要的小伙伴可以參考下2015-11-11

