在AMPS中,使用内存池来管理内存,具体机制见之前的文章《AMPS:内存管理(二)》,在代码中,使用了两种实现方式,第一种是数组+单链表。今天先看看这个方式下的内存池实现。
AMPS_MemoryMgt.h
#ifndef __HEADER_AMPS_MEMORY_MGMT_H__ #define __HEADER_AMPS_MEMORY_MGMT_H__ #include "AMPS_Defines.h" #include "AMPS_Trace.h" #ifdef __cplusplus extern "C" { #endif typedef void*(*AMPS_InternalMallocCallback)(int r_unSize); typedef void*(*AMPS_InternalReallocCallback)(void* r_pvData, int r_unSize); typedef void(*AMPS_InternalFreeCallback)(void* r_pvData); // we need at least these many buffers // _ // 1- 8 bytes | // 2- 16 bytes | // 3- 32 bytes > Lower limit chunks // 4- 64 bytes | // 5- 128 bytes | // _ // _ // 6- 8 Kbytes | // 7- 16 Kbytes > upper limit chunks // 8- 32 Kbytes | // 9- 64 Kbytes | // _ #define MAX_SIZE 65536 + 1 #define LN_2 .6931471805599453 //val = log(x)/log(2) #define LN2_OF_1024 10 #define NO_OF_SMALL_MEM_POOLS 32 //1024/32 #define NO_OF_LARGE_MEM_POOLS 10 #define NO_OF_BLOCKS_OF_SMALL_MEM_POOL 1000 #define MINIMUM_SMALL_MEM_BLOCK_SIZE 32 #define NO_OF_BLOCKS_OF_LARGE_MEM_POOL 500 #define MINIMUM_LARGE_MEM_BLOCK_SIZE 2048 #define OFFSET 21 // LN2_OF_1024 + 1024/32 -1 typedef struct _node t_node; typedef struct _MemoryPool t_MemoryPool; typedef struct _MemContext t_MemContext; //requested size lies in the lower range of allocated buffers #define GET_MEM_BUFFER_INDEX(size) (size <= 1024 ? (size -1)/32 : (int)(ceil((float)(log(size)/LN_2))) + OFFSET) #define GET_INDEX_FROM_BUFFER(dataPtr) (*((int*)(dataPtr - sizeof(int))) < NO_OF_SMALL_MEM_POOLS+NO_OF_LARGE_MEM_POOLS ? *((int*)(dataPtr - sizeof(int))) : AMPS_ERROR_FAILURE) /*链表结点结构*/ struct _node { t_node* poAMPSSListNext; t_node* poAMPSSListPrev; }; /*池中链表结构*/ struct _MemoryPool { t_node* poHead; unsigned char* puchBuffer; unsigned int nSize; t_MemoryPool* poMemoryPoolNext; }; /*内存池结构*/ struct _MemContext { AMPS_InternalMallocCallback pfAMPS_InternalMallocCallback; AMPS_InternalReallocCallback pfAMPS_InternalReallocCallback; AMPS_InternalFreeCallback pfAMPS_InternalFreeCallback; int nNoOfMallocWithoutFree; int nNoOfMallocWithoutFree2; AMPS_BOOL bMMEnable; t_MemoryPool poMemoryPools[NO_OF_SMALL_MEM_POOLS+NO_OF_LARGE_MEM_POOLS]; int nMallocCounts[NO_OF_SMALL_MEM_POOLS+NO_OF_LARGE_MEM_POOLS]; }; void* MM_Init(int r_bMMEnable); void MM_Cleanup(void); void MM_BufferInit(t_MemoryPool* r_poMemoryPools, int r_nBufferIndex, int r_nSize, int r_nChunks); void MM_BufferDestroy(t_MemoryPool* r_poMemoryPools); void* AMPS_InternalMalloc(int r_nSize); void* AMPS_InternalRealloc(void* r_pvData, int r_nSize); void AMPS_InternalFree(void* r_pvData); void* OS_Malloc(int r_nSize); void* OS_Realloc(void* r_pvData, int r_nSize); void OS_Free(void* r_pvData); void* MM_Malloc(int r_nSize); void* MM_Realloc(void* r_pvData, int r_unSize); void MM_Free(void* r_pvData); void MM_BufferNew(int r_nSize); int MM_GetNoOfChunks(int r_nSize); void MM_BufferShow(t_MemoryPool* r_poMemoryPools, int r_nSize); void MM_BufferDump(unsigned char* r_puchBuff, int r_nSize); void MM_CalculateAndDisplayMemoryStats (void); #ifdef __cplusplus } #endif #endif /* __HEADER_AMPS_MEMORY_MGMT_H__ */AMPS_MemoryMgt.c
#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 node poNextMemoryPool = &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 correctly void 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); }