AMPS:内存管理模块源码解读(一)
在AMPS中,使用内存池来管理内存,具体机制见之前的文章《AMPS:内存管理(二)》,在代码中,使用了两种实现方式,第一种是数组+单链表。今天先看看这个方式下的内存池实现。
AMPS_MemoryMgt.h
#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include "AMPS_LinkList.h"#include "AMPS_Core.h"#include "AMPS_Defines.h"#include "AMPS_MemMgt.h"t_MemContext* g_poMemContext;int g_nTotalMallocs = 0;int g_nTotalFrees = 0;/*****************************************************************函数名称: AMPS_InternalMalloc功能描述: 内部的内存分配函数入参:: int r_unSize 待分配的字节数出参: 返回值: void* 分配完成后的内存块指针*****************************************************************/void* AMPS_InternalMalloc(int r_unSize){/*g_poMemContext->nNoOfMallocWithoutFree++;if(g_poMemContext->nNoOfMallocWithoutFree > 17600){printf("AMPS_InternalMalloc: ======================= App Memory Count %d\n", g_poMemContext->nNoOfMallocWithoutFree);}*///return(g_poMemContext->pfAMPS_InternalMallocCallback(r_unSize));void* pvReturnValue = NULL;pvReturnValue = malloc(r_unSize);if(NULL == pvReturnValue){printf("OS_Malloc: malloc failed for size %d.\n", r_unSize);return NULL;}memset(pvReturnValue, 0, r_unSize);return pvReturnValue;}/*****************************************************************函数名称: AMPS_InternalRealloc功能描述: 重新分配内存入参:: void* r_pvData 待重新分配的内存块 int r_unSize 需要增加的字节数出参: 返回值: void* 分配完成后的内存块指针*****************************************************************/void* AMPS_InternalRealloc(void* r_pvData, int r_unSize){ //return(g_poMemContext->pfAMPS_InternalReallocCallback(r_pvData, r_unSize));void* pvReturnValue = NULL;pvReturnValue = realloc(r_pvData, r_unSize); if(NULL == pvReturnValue){printf("OS_Realloc: realloc failed for size %d.\n", r_unSize);return NULL;}return pvReturnValue;}/*****************************************************************函数名称: AMPS_InternalFree功能描述: 内存释放入参:: void* r_pvData 待释放内存地址出参: 返回值: void*****************************************************************/void AMPS_InternalFree(void* r_pvData){/*g_poMemContext->nNoOfMallocWithoutFree--;if(g_poMemContext->nNoOfMallocWithoutFree < 17600){printf("AMPS_InternalFree: =+=+=+=+=+=+=+=+=+=+=+=+= App Memory Count %d\n", g_poMemContext->nNoOfMallocWithoutFree);}*///g_poMemContext->pfAMPS_InternalFreeCallback(r_pvData);free(r_pvData);r_pvData = NULL;}/*****************************************************************函数名称: OS_Malloc功能描述: 操作系统提供的内存分配入参:: int r_unSize出参: 返回值: void*****************************************************************/void* OS_Malloc(int r_unSize){ void* pvReturnValue = NULL; pvReturnValue = malloc(r_unSize);if(NULL == pvReturnValue){printf("OS_Malloc: malloc failed for size %d.\n", r_unSize);return NULL;} memset(pvReturnValue, 0, r_unSize);//g_nTotalMallocs++;//printf("total mallocs=%d.\n", g_nTotalMallocs); return pvReturnValue;}/*****************************************************************函数名称: OS_Realloc功能描述: 操作系统提供的内存重新分配入参: void* r_pvData int r_unSize出参: 返回值: void*****************************************************************/void* OS_Realloc(void* r_pvData, int r_unSize){ void* pvReturnValue = NULL; pvReturnValue = realloc(r_pvData, r_unSize); if(NULL == pvReturnValue){printf("OS_Realloc: realloc failed for size %d.\n", r_unSize);return NULL;} return pvReturnValue;}/*****************************************************************函数名称: OS_Free功能描述: 操作系统提供的内存释放入参: void* r_pvData出参: 返回值: void*****************************************************************/void OS_Free(void* r_pvData){/*if(NULL == r_pvData){printf("OS_Free: NULL pointer.\n");return;}*/ free(r_pvData);//g_nTotalMallocs--;//printf("total frees=%d.\n", g_nTotalMallocs); r_pvData = NULL;}//inialize all the blocks here..//array of structures of different sized chunks//|0| = |2k|-|2k|-|2k|...//|1| = |4k|-|4k|-|4k|...//|2| = |6k|-|6k|-|6k|.../*****************************************************************函数名称: MM_Init功能描述: 内存管理模块初始化入参: int r_bMMEnable 是否使用内存池出参: 返回值: void******************************************************************/void* MM_Init(int r_bMMEnable){int i,j =0;int nLargeMemSize = 0; /*内存模块指针*/g_poMemContext = malloc(sizeof(t_MemContext));if(NULL == g_poMemContext){printf("MM_Init: malloc is failed for g_poMemContext.\n");return NULL;}g_poMemContext->nNoOfMallocWithoutFree = 0;g_poMemContext->bMMEnable = (AMPS_BOOL)r_bMMEnable; /*是否使用内存池管理内存*/if(AMPS_TRUE == r_bMMEnable){ /*初始化小块内存池,池中有42个链表(32个小块内存链表+10个大块内存链表) 这些链表有32k,64k,96K....的内存,链表的每一个结点,分别是32B, 64B.... 同一个链表中各结点大小一样,结点中间都会有一个32位整形的索引值,比如第 一个链表的结构如下: |0|32B|0|32B|0|32B|......*/for(i=0, j=1; i<NO_OF_SMALL_MEM_POOLS; i++,j++) //low limit elements{printf("Initializing buffer with size = %d at index = %d \n", nLargeMemSize, i);MM_BufferInit(&g_poMemContext->poMemoryPools[i], i, j*MINIMUM_SMALL_MEM_BLOCK_SIZE, NO_OF_BLOCKS_OF_SMALL_MEM_POOL);} /*初始化大内存块,原理与小内存块初始化一样*/nLargeMemSize = MINIMUM_LARGE_MEM_BLOCK_SIZE;for(i=0,j=1; i<NO_OF_LARGE_MEM_POOLS; i++,j++){printf("Initializing buffer with size = %d at index = %d \n", nLargeMemSize, NO_OF_SMALL_MEM_POOLS+i);MM_BufferInit(&g_poMemContext->poMemoryPools[NO_OF_SMALL_MEM_POOLS+i], NO_OF_SMALL_MEM_POOLS+i, nLargeMemSize, NO_OF_BLOCKS_OF_LARGE_MEM_POOL);nLargeMemSize = nLargeMemSize*2;} /*内存操作函数*/g_poMemContext->pfAMPS_InternalMallocCallback = MM_Malloc;g_poMemContext->pfAMPS_InternalReallocCallback = MM_Realloc;g_poMemContext->pfAMPS_InternalFreeCallback = MM_Free;}else{ /*不使用内存池,直接使用操作系统提供的内存分配函数*/g_poMemContext->pfAMPS_InternalMallocCallback = OS_Malloc;g_poMemContext->pfAMPS_InternalReallocCallback = OS_Realloc;g_poMemContext->pfAMPS_InternalFreeCallback = OS_Free;}/*j = i;MM_BufferInit(&g_poMemContext->poMemoryPools[j], j, 262144, NO_OF_BLOCKS_OF_LARGE_MEM_POOL);*/return g_poMemContext;}/*****************************************************************函数名称: MM_Cleanup功能描述: 内存管理模块销毁入参: int r_bMMEnable出参: 返回值: void******************************************************************/void MM_Cleanup(void){t_MemContext* poMemContext = g_poMemContext;t_MemoryPool* poNextMemoryPool = NULL;t_MemoryPool* poPrevMemoryPool = NULL;int i =0;if(AMPS_TRUE == g_poMemContext->bMMEnable){if(NULL != poMemContext){ /*逐一释放内存池中各链表结点内存*/for(i=0; i<NO_OF_SMALL_MEM_POOLS+NO_OF_LARGE_MEM_POOLS; i++){free(poMemContext->poMemoryPools[i].puchBuffer);poNextMemoryPool = poMemContext->poMemoryPools[i].poMemoryPoolNext;while(NULL != poNextMemoryPool){poPrevMemoryPool = poNextMemoryPool;poNextMemoryPool = poNextMemoryPool->poMemoryPoolNext;MM_BufferDestroy(poPrevMemoryPool);free(poPrevMemoryPool);}}}} /*释放内存池指针所占内存*/free(poMemContext);}/*****************************************************************函数名称: MM_Malloc功能描述: 内存管理模块内存分配入参: int r_nSize出参: 返回值: void******************************************************************/void* MM_Malloc(int r_nSize){t_MemContext* poMemContext = g_poMemContext;t_MemoryPool* poMemoryPool = NULL;t_node* poNode = NULL; /*根据大小获取一个偏移量,用于在内存池中查找对应的内存链表*/int index = GET_MEM_BUFFER_INDEX(r_nSize);if(AMPS_ERROR_FAILURE == index){printf("AMPS_InternalMalloc: Invalid size arguement given %d \n", r_nSize);return NULL;} /*分配的内存块总数目加1*/poMemContext->nMallocCounts[index]++; /*指向找到的内存链表*/poMemoryPool = &poMemContext->poMemoryPools[index]; /*从链表头获取一个节点*/poNode = poMemoryPool->poHead;poMemoryPool->poHead = poMemoryPool->poHead->poAMPSSListNext;if(NULL != poMemoryPool->poHead){poMemoryPool->poHead->poAMPSSListPrev = NULL;}else{ /*如果链表中无可用内存,重新分配*/MM_BufferNew(poMemoryPool->nSize);}memset((void*)poNode, 0, r_nSize);return poNode;}/*****************************************************************函数名称: MM_Realloc功能描述: 内存管理模块重新内存分配入参: void* r_pvData 原内存指针 int r_unSize 大小出参: 返回值: void******************************************************************/void* MM_Realloc(void* r_pvData, int r_unSize){unsigned char* newptr = NULL;int oldBuffSize = -1;int index = 0;t_MemContext* poMemContext = g_poMemContext;unsigned char* puchData = (unsigned char*)r_pvData;if(NULL == puchData){return NULL;} /*计算当前所在内存指针在池中的链表索引*/index = GET_INDEX_FROM_BUFFER(puchData);if(AMPS_ERROR_FAILURE == index){printf("AMPS_InternalRealloc: Invalid pvData pointer given for realloc \n");return NULL;}oldBuffSize = poMemContext->poMemoryPools[index].nSize;newptr = AMPS_InternalMalloc(r_unSize);if(NULL == newptr){printf("AMPS_InternalRealloc: Unable to allocate new memory for requested size = %d \n", r_unSize);return NULL;}memcpy(newptr, puchData, oldBuffSize);AMPS_InternalFree(puchData);return newptr;}/*****************************************************************函数名称: MM_Free功能描述: 内存管理模块内存释放入参: void* r_pvData出参: 返回值: void*****************************************************************/void MM_Free(void* r_pvData){t_MemContext* poMemContext = g_poMemContext;unsigned char* puchData = (unsigned char*)r_pvData;t_MemoryPool* poMemoryPool = NULL;t_node* poNode = NULL; int index = 0; if (NULL == r_pvData) { return; } /*获取池中链表索引*/ index = GET_INDEX_FROM_BUFFER(puchData); if(AMPS_ERROR_FAILURE == index){printf("AMPS_InternalFree: Invalid pvData pointer given for free \n");return ;}//poMemContext->nMallocCounts[index]--; /*从链表头删除此结点*/poMemoryPool = &poMemContext->poMemoryPools[index];poNode = (t_node*)puchData;poNode->poAMPSSListPrev = NULL;poNode->poAMPSSListNext = poMemoryPool->poHead;if(NULL != poMemoryPool->poHead) //there was no node left in the current buffer so poAMPSSListHead was NULL{poMemoryPool->poHead->poAMPSSListPrev = poNode;}poMemoryPool->poHead = poNode;}/*****************************************************************函数名称: MM_BufferInit功能描述: 内存链表头结点入参: t_MemoryPool* r_poMemoryPool 内存池中结点指针 int indexOfBuff 此结点在内存池中的位置 int size 待分配的各结点内存大小 int chunks 结点个数出参: 返回值: void******************************************************************/// Mark this buffer for use..//1- initialize the poAMPSSListHead.//2- write the chunk array index into it.void MM_BufferInit(t_MemoryPool* r_poMemoryPool, int indexOfBuff, int size, int chunks){t_MemoryPool* poMemoryPool = r_poMemoryPool;t_node* prev_node = NULL;t_node* node = NULL;unsigned int* indexTag = 0;int i=0; /*以下假设indexOfbuff=0,size=32,chunks=1000进行讲解*/ /*分配所表示链表占用的总内存*/poMemoryPool->puchBuffer = malloc(size*chunks + chunks*sizeof(int)); /*链表结点个数*/poMemoryPool->nSize = size; /*下一个结点置NULL*/ poMemoryPool->poMemoryPoolNext = NULL; /*内存前4个字节置为当前总链表数组偏移量*/indexTag = (unsigned int*)&poMemoryPool->puchBuffer[0];*indexTag = indexOfBuff; /*第二个结点从内存块的第4个字节开始,因为前四个字已经存放了下标*/node = (t_node*)&poMemoryPool->puchBuffer[sizeof(int)];node->poAMPSSListPrev = NULL;node->poAMPSSListNext = NULL; /*链表头指针这个结点*/poMemoryPool->poHead = node;prev_node = node;for(i=1; i< chunks; i++){int index = 0; /*跳过前四个结点,中间再相隔32个字节*/indexTag = (unsigned int*)&poMemoryPool->puchBuffer[i*size + i* sizeof(int)];*indexTag = indexOfBuff; /*再计算下一个节点的位置,最终形成了一个这样的链表: 每个结点前4个字节值一样,存放当前链表在整个池中的便宜量, 然后接着是32个字节。再下来就是下一个节点,其有1000个这样的结点*/index = i*size + ((i*sizeof(int))+sizeof(int));node = (t_node*)&poMemoryPool->puchBuffer[index];prev_node->poAMPSSListNext = node;node->poAMPSSListPrev = prev_node;node->poAMPSSListNext = NULL;prev_node = node;}}/*****************************************************************函数名称: MM_BufferDestroy功能描述: 内存链表结点销毁入参: t_MemoryPool* r_poMemoryPool 内存池中结点指针出参: 返回值: void*****************************************************************/void MM_BufferDestroy(t_MemoryPool* r_poMemoryPool){if(NULL != r_poMemoryPool->puchBuffer){free(r_poMemoryPool->puchBuffer);}r_poMemoryPool->poHead = NULL;r_poMemoryPool->puchBuffer = NULL;}/*****************************************************************函数名称: MM_BufferNew功能描述: 新分配一个内存链表入参: tr_nSize 大小出参: 返回值: void*****************************************************************/void MM_BufferNew(int r_nSize){int chunks = 0;t_MemoryPool* poNextMemoryPool = NULL;t_MemoryPool* poNewMemBuff = NULL;t_MemContext* poMemContext = (t_MemContext*)g_poMemContext; /*获取池中链表索引*/int index = GET_MEM_BUFFER_INDEX(r_nSize);if(AMPS_ERROR_FAILURE == index){printf("MM_BufferNew: Unable to get new buffer \n");return ;} /*计算需要的块个数*/chunks = MM_GetNoOfChunks(r_nSize)/2;poNewMemBuff = malloc(sizeof(t_MemoryPool));if(NULL == poNewMemBuff){printf("MM_BufferNew: Unable to malloc for new buffer \n");return ;} /*建立一个新的内存链表*/MM_BufferInit(poNewMemBuff, index, r_nSize, chunks); /*把新分配的链表挂在内存池上*///go to last node to add a new nodepoNextMemoryPool = &poMemContext->poMemoryPools[index];while(NULL != poNextMemoryPool->poMemoryPoolNext){poNextMemoryPool = poNextMemoryPool->poMemoryPoolNext;}poNextMemoryPool->poMemoryPoolNext = poNewMemBuff;poMemContext->poMemoryPools[index].poHead = poNewMemBuff->poHead;}/*****************************************************************函数名称: MM_GetNoOfChunks功能描述: 根据大小,计算所需要的内存块个数(一个块的大小为32B)入参: tr_nSize 大小出参: 返回值: int*****************************************************************/int MM_GetNoOfChunks(int bufferSize){if(bufferSize < 1024){int sizeIndex = (bufferSize-1)/32;switch(sizeIndex){case 0:return 100;break;case 1:return 125;break;case 2:return 100;break;case 3:return 100;break;case 4:return 100;break;default :return 28;}}else{return 100;}}/*****************************************************************函数名称: MM_BufferShow功能描述: 遍历内存链表入参: t_MemoryPool* r_poMemoryPool tr_nSize 大小出参: 返回值: int*****************************************************************///simply debug utility function to see if link list has been created correctlyvoid MM_BufferShow(t_MemoryPool* r_poMemoryPool, int r_nSize){t_MemoryPool* poMemoryPool = r_poMemoryPool;t_node* poNode = NULL;int i=0;poNode = (t_node*)&poMemoryPool->poHead;while(NULL != poNode->poAMPSSListNext){poNode = poNode->poAMPSSListNext;i++;}}void MM_BufferDump(unsigned char* buff, int size){int i=0;for(i=0; i< size; i++){ //printf%.2x ,", buff[i]);if(i%8 == 0 && i!=0){ //printf\n");}}}/*****************************************************************函数名称: MM_CalculateAndDisplayMemoryStats功能描述: 查看内存池使用情况(总大小,已分配大小)入参: void出参: 返回值: int*****************************************************************/void MM_CalculateAndDisplayMemoryStats (void){ int i =0,j=0;int nLargeMemSize = MINIMUM_LARGE_MEM_BLOCK_SIZE; int nTotalMemory = 0;printf(" ====== Memory Usage Count for Small memory chunks.=====\n");for(i=0,j=1; i< NO_OF_SMALL_MEM_POOLS; i++,j++){if(0 != g_poMemContext->nMallocCounts[i]){ nTotalMemory += ((g_poMemContext->nMallocCounts[i] * (j*32))/1024);printf("Pool Size = %d No Of Mallocs = %d total = %d kilo bytes\n", j*32, g_poMemContext->nMallocCounts[i], ((g_poMemContext->nMallocCounts[i] * (j*32))/1024));}}printf(" ====== Memory Usage Count for Large memory chunks.=====\n");for(i=0,j=1; i< NO_OF_LARGE_MEM_POOLS; i++,j++){if(i == 0){nLargeMemSize = nLargeMemSize;}else { nLargeMemSize = nLargeMemSize * 2; } if(0 != g_poMemContext->nMallocCounts[NO_OF_SMALL_MEM_POOLS + i]) { nTotalMemory += ((g_poMemContext->nMallocCounts[NO_OF_SMALL_MEM_POOLS+i] * (nLargeMemSize))/1024); printf("Pool Size = %d No Of Mallocs = %d total = %d kilo bytes\n", nLargeMemSize, g_poMemContext->nMallocCounts[NO_OF_SMALL_MEM_POOLS+i], ((g_poMemContext->nMallocCounts[NO_OF_SMALL_MEM_POOLS+i] * (nLargeMemSize))/1024)); } } printf("Total Memory Consumed is = %d Megs.\n", nTotalMemory/1024);}