使用C語言實(shí)現(xiàn)內(nèi)存池的示例代碼
概要
所謂內(nèi)存池,顧名思義和線程池的設(shè)計(jì)原理是一樣的,為了減少頻繁申請釋放內(nèi)存而帶來的資源消耗,減少釋放內(nèi)存后產(chǎn)生的內(nèi)存碎片。
設(shè)計(jì)理念
為了方便管理內(nèi)存池的設(shè)計(jì)通常是劃分出一定數(shù)量的內(nèi)存塊,這些內(nèi)存塊的長度是一樣的; 用戶申請內(nèi)存塊時(shí)返回空閑的內(nèi)存塊地址,如果內(nèi)存塊使用完畢就釋放該內(nèi)存塊,將該內(nèi)存塊置為空閑狀態(tài),放回到內(nèi)存池,供以后使用。
內(nèi)存池的設(shè)計(jì)核心幾大模塊:創(chuàng)建內(nèi)存池,申請內(nèi)存塊,釋放內(nèi)存塊,銷毀內(nèi)存池!
當(dāng)然這只是常用的內(nèi)存池設(shè)計(jì),實(shí)際項(xiàng)目中可以根據(jù)需求設(shè)計(jì)不同的線程池:內(nèi)存塊的長度不一,可以提供自定義的內(nèi)存塊設(shè)計(jì)等兼容性更高的內(nèi)存池。
本文只做內(nèi)存池原理的講解和實(shí)現(xiàn)最基礎(chǔ)的內(nèi)存池!更多的功能根據(jù)實(shí)際的需求進(jìn)行擴(kuò)展即可。
內(nèi)存池的設(shè)計(jì)思路有很多,可以給予鏈表,數(shù)組,隊(duì)列等進(jìn)行設(shè)計(jì),核心就是怎么存儲內(nèi)存塊信息;本期是基于鏈表進(jìn)行的內(nèi)存池設(shè)計(jì)。
模塊設(shè)計(jì)
內(nèi)存池結(jié)構(gòu)
內(nèi)存塊節(jié)點(diǎn)結(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é)點(diǎn),插入到空閑鏈表
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é)點(diǎn)
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)完成,在實(shí)際項(xià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語言實(shí)現(xiàn)內(nèi)存池的示例代碼的文章就介紹到這了,更多相關(guān)C語言實(shí)現(xiàn)內(nèi)存池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用c++實(shí)現(xiàn)OpenCV圖像橫向&縱向拼接
這篇文章主要介紹了使用c++實(shí)現(xiàn)OpenCV圖像橫向&縱向拼接,文中有圖像拼接函數(shù),可以實(shí)現(xiàn)如“長圖拼接王”這類小程序的類似功能,大家可以將該函數(shù)封裝在軟件中自由使用2021-08-08
C語言修煉之路悟徹?cái)?shù)組真妙理?巧用下標(biāo)破萬敵上篇
在C語言和C++等語言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來指向若干個字符串,使字符串處理更加方便、靈活2022-02-02
C++?Qt開發(fā)之運(yùn)用QJSON模塊解析數(shù)據(jù)
JSON(JavaScript?Object?Notation)是一種輕量級的數(shù)據(jù)交換格式,它易于人閱讀和編寫,也易于機(jī)器解析和生成,本文主要介紹了Qt如何運(yùn)用QJson組件的實(shí)現(xiàn)對JSON文本的靈活解析功能,需要的可以參考下2024-01-01
C++ 隨機(jī)數(shù)字以及隨機(jī)數(shù)字加字母生成的案例
這篇文章主要介紹了C++ 隨機(jī)數(shù)字以及隨機(jī)數(shù)字加字母生成的案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Linux C 獲取進(jìn)程退出值的實(shí)現(xiàn)代碼
本篇文章是對在Linux下使用c語言獲取進(jìn)程退出值的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

