在AMPS中,使用內存池來管理內存,具體機制見之前的文章《AMPS:內存管理(二)》,在代碼中,使用了兩種實現方式,第一種是數組+單鏈表。今天先看看這個方式下的內存池實現。 AMPS_MemoryMgt.h [cpp] #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__ */ #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 [cpp] view plaincopyprint? #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); } #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); }