AMPS:記憶體管理模組源碼解讀(二)

來源:互聯網
上載者:User

  上節看了AMPS中通過數組+單鏈表實現的記憶體池,本節看看另一個實現方式。此方法思路如下:其記憶體池結構為一個存放已指派記憶體資訊的雙鏈表,一個表示記憶體池大小的變數,一個指向當前記憶體鏈表結點的指標鏈表,如下:

/*記憶體池結構*/struct _newMMContext{    t_AMPSDList* memBuffList;      /*結點鏈表*/    int nSizeOfBuff;               /*池大小*/t_AMPSSList* poCurrentListPtr; /*當前所指結點*/};

其中,記憶體結點鏈表各結點結構如下:

/*記憶體鏈表結點結構*/struct _newMM_MemoryNode{int nAllocatedBytesInBlock; /*已指派位元組數*/char* pchCurrPtrInBlock;    /*當前指標*/char* memBuff;              /*記憶體*/};

在memBuff中,每分配一個記憶體塊,當前phCurrPtrInBlock向後移動需要分配的位元組數+記憶體描述資訊區。

其中記憶體資訊描述區的結構如下:

/*記憶體鏈表描述結構*/struct _newMMBuffDescriptor{char markerBytes[4]; /*存放值DEAD,此值在分配時寫,在釋放時比較,如不一致,說明記憶體已出錯。*/int nSizeOfBuff;     /*此塊記憶體的大小*/t_AMPSSList* dlistNode;/*存放已指派的記憶體結點指標*/};

此結構主要用於在記憶體釋放時判斷是否有重複釋放或者猜踩記憶體的現象,前面markerBytes為每一小塊記憶體的開頭資訊,固定值"DEAD",相當於一個檢驗資訊。

下面看看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" {#endiftypedef struct  _newMMContext     t_NewMMContext;typedef struct  _newMM_MemoryNode t_NewMM_MemoryNode;typedef struct  _newMMBuffDescriptor t_NewMMBuffDescriptor;typedef struct  _newMemSizeCmp         t_NewMemSizeCmp;/*記憶體池結構*/struct _newMMContext{    t_AMPSDList* memBuffList;      /*結點鏈表*/    int nSizeOfBuff;               /*池大小*/t_AMPSSList* poCurrentListPtr; /*當前所指結點*/};/*記憶體鏈表結點結構*/struct _newMM_MemoryNode{int nAllocatedBytesInBlock; /*已指派位元組數*/char* pchCurrPtrInBlock;    /*當前指標*/char* memBuff;              /*記憶體*/};/*記憶體鏈表描述結構*/struct _newMMBuffDescriptor{char markerBytes[4]; /*存放值DEAD,此值在分配時寫,在釋放時比較,如不一致,說明記憶體已出錯。*/int nSizeOfBuff;     /*此塊記憶體的大小*/t_AMPSSList* dlistNode;/*存放已指派的記憶體結點指標*/};/*記憶體大小比較結構*/struct _newMemSizeCmp{int nSizeRequired;int maxSize;};void* MM_New_Init(int nSizeOfBuff);int compareAvailableBytes(void* size, void* listData);void* MM_New_Malloc(void* mm_Object,int nSize);void MM_New_Free(void* mm_Object,char* buffToFree);#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"/*****************************************************************函數名稱: createNewMemNode功能描述: 建立記憶體結點入參:      int nSizeOfBuff 大小 出參:            傳回值:      t_NewMM_MemoryNode******************************************************************/t_NewMM_MemoryNode* createNewMemNode(int nSizeOfBuff){t_NewMM_MemoryNode* newNode = NULL;    /*分配一塊記憶體,前面存放結點資訊,後面是結點實際的塊大小*/char* pchTempPtr = (char*)OS_Malloc(sizeof(t_NewMM_MemoryNode) + nSizeOfBuff);newNode = (t_NewMM_MemoryNode*)pchTempPtr;if(NULL != newNode){newNode->nAllocatedBytesInBlock = 0; newNode->memBuff = (char*)(pchTempPtr + sizeof(t_NewMM_MemoryNode));                           newNode->pchCurrPtrInBlock = newNode->memBuff;}else{return NULL;}return newNode;}/*分配與釋放計數器*/int g_nNumAlloc=0; int g_nNumFree=0;/*****************************************************************函數名稱: MM_New_Init功能描述: 記憶體模組初始化入參:      int nSizeOfBuff 大小 出參:            傳回值:      t_NewMM_MemoryNode******************************************************************/void* MM_New_Init(int nSizeOfBuff){    /*建立一個記憶體池*/t_NewMMContext* newContext = OS_Malloc(sizeof(t_NewMMContext));t_AMPSDList* memBuffList = NULL;        if(NULL == newContext){printf("NewMM: unable to create new memory context---out of memory\n");return NULL;}    /*記憶體池大小*/newContext->nSizeOfBuff = nSizeOfBuff;    /*初始化記憶體鏈表*/memBuffList = DList_Init(&memBuffList);    /*鏈表掛在記憶體池中*/if(NULL != memBuffList){t_NewMM_MemoryNode* newNode = NULL;newContext->memBuffList = memBuffList;newNode = createNewMemNode(nSizeOfBuff);if(NULL != newNode){printf("init mem: allocated new buffer %p\n",newNode);g_nNumAlloc++;/*已指派結點數+1*/newContext->poCurrentListPtr = DList_Append(memBuffList,(void*)newNode);}else{OS_Free(newContext);DList_Free(&memBuffList,NULL);return NULL;}}else{        OS_Free(newContext);    DList_Free(&memBuffList,NULL);    return NULL;}    return newContext;}/*****************************************************************函數名稱: compareAvailableBytes功能描述: 看是否有可用的記憶體入參:      void* size 大小      void* listData 鏈表出參:            傳回值:      t_NewMM_MemoryNode******************************************************************/int compareAvailableBytes(void* size, void* listData){    t_NewMemSizeCmp* sizeCmp = (t_NewMemSizeCmp*)size;t_NewMM_MemoryNode* memNode = (t_NewMM_MemoryNode*)listData;//printf("sizeCmp=%p AND memNode=%p \n", sizeCmp, memNode);    /*結點內總記憶體塊指標,指向結尾*/char* endOfBuff = memNode->memBuff + sizeCmp->maxSize;    /*判斷結點內剩餘的記憶體是否滿足所要求分配的*/if( (endOfBuff - memNode->pchCurrPtrInBlock) >= sizeCmp->nSizeRequired ){//printf("Available=%d AND sizeCmp->nSizeRequired=%d \n", (endOfBuff - memNode->pchCurrPtrInBlock), sizeCmp->nSizeRequired);   return 0;}return -1;}/*****************************************************************函數名稱: MM_New_Malloc功能描述: 分配記憶體入參:      void* mm_Object 記憶體池指標      int nSize 大小出參:            傳回值:      t_NewMM_MemoryNode******************************************************************/void* MM_New_Malloc(void* mm_Object,int nSize){    t_NewMMContext* mmContext = (t_NewMMContext*)mm_Object;    int nActualSize = 0;    t_AMPSSList* listNode = NULL;    t_NewMM_MemoryNode* memNode = NULL;//printf("MALLOC: Ctxt=%p, Size=%d \n", mmContext, nSize);if(nSize < 0){        printf("MALLOC: bad allocation request size %d\n",nSize);return NULL;}if(NULL == mm_Object){return NULL;}        /*要求的大小大於池中允許大小*/if(nSize > mmContext->nSizeOfBuff){printf("MALLOC: too large allocation request for size %d: the memory manager supports up to %d bytes requests\n",nSize,mmContext->nSizeOfBuff);return NULL;}if(0 == nSize){nSize = 4;/*後面位移使用*/}    /*指定大小為實際要分配的大小+記憶體比較頭大小*/nActualSize = nSize + sizeof(t_NewMMBuffDescriptor);    /*向後移4個位元組*/nActualSize =  ((nActualSize + 3) >> 2) << 2;   // go to next four byte boundary    //printf("MALLOC: Ctxtt=%p, nActualSize = %d, On mmContext->memBuffList =%p \n", mmContext, nActualSize, mmContext->memBuffList);    /*指向池當前指標*/listNode = mmContext->poCurrentListPtr;if(NULL != listNode){        t_NewMemSizeCmp sizeCmp;        sizeCmp.nSizeRequired = nActualSize;         sizeCmp.maxSize       = mmContext->nSizeOfBuff;        /*比較是否有記憶體可供分配*/if( -1 == compareAvailableBytes((void*)&sizeCmp, listNode->pvData)){listNode = NULL;}    //listNode = DList_Search(mmContext->memBuffList,compareAvailableBytes,(void*)&sizeCmp);}    /*有則取已有記憶體結點,無則分配一個新的結點*///printf("MALLOC: Ctxt=%p, nSize (after DListSearch)=%d listNode=%p  \n", mmContext, nSize, listNode);    if(NULL != listNode){memNode = (t_NewMM_MemoryNode*)listNode->pvData;//printf("Ctxt=%p,memNode->memBuff=%p, memNode->pchCurrPtrInBlock=%p \n",mmContext, memNode->memBuff, memNode->pchCurrPtrInBlock);}else {t_NewMM_MemoryNode* newNode = createNewMemNode(mmContext->nSizeOfBuff);if(NULL!= newNode){g_nNumAlloc++;             listNode = DList_Append(mmContext->memBuffList,(void*)newNode); if(NULL == listNode)             { printf("****new mm malloc: dlist append failed..\n"); OS_Free(newNode); return NULL;             } //printf("Ctxt=%pallocated new buffer %p, total buffers allocated=%d, listNode=%p \n",mmContext, newNode, g_nNumAlloc, listNode); memNode = newNode; mmContext->poCurrentListPtr = listNode;}else{printf("MALLOC: unable to allocate new node\n");return NULL;}}{         /*執向取到的結點內的記憶體塊當前指標*/         char* tempPtr = memNode->pchCurrPtrInBlock; t_NewMMBuffDescriptor* buffDescriptorPtr = (t_NewMMBuffDescriptor*)tempPtr;         /*記憶體描述內容前4個位元組賦值DEAD*/         memcpy(buffDescriptorPtr->markerBytes,"DEAD",4);         /*此塊記憶體大小*/         buffDescriptorPtr->nSizeOfBuff = nActualSize;         /*存放當前記憶體結點指標*/         buffDescriptorPtr->dlistNode = listNode;  // store the back ptr to mem node         /*結點內記憶體配置位元組數遞增*/ memNode->nAllocatedBytesInBlock += nActualSize;         /*跳過記憶體描述資訊區*/ tempPtr += sizeof(t_NewMMBuffDescriptor);  // tempPtr now points to writeable area of this buffer for the application         /*結點內當前指標向後移動*/         memNode->pchCurrPtrInBlock += nActualSize; // current ptr now advances to next buffer to be allocated     memset(tempPtr,0,nSize); // zero out the contents of the allocated memory //printf("MALLOC: mmContext=%p: memNode->nAllocatedBytesInBlock=%d and Requested Size =%d\n", mmContext, memNode->nAllocatedBytesInBlock, nSize); return tempPtr;}}/*****************************************************************函數名稱: MM_New_Free功能描述: 分配釋放入參:      void* mm_Object 記憶體池指標      char* buffToFree 要釋放的記憶體指標出參:            傳回值:      void*****************************************************************/void MM_New_Free(void* mm_Object,char* buffToFree){t_NewMMContext* mmContext = (t_NewMMContext*)mm_Object;char* tempPtr = buffToFree;t_NewMM_MemoryNode* memNode = NULL;t_AMPSSList* listNode = NULL;t_NewMMBuffDescriptor* buffDescriptorPtr = NULL;    /*要釋放的指標向前移動,找到記憶體描述區*/tempPtr -= sizeof(t_NewMMBuffDescriptor);buffDescriptorPtr = (t_NewMMBuffDescriptor*)tempPtr;        if(NULL == tempPtr){        printf("FREE: buffer descriptor ptr is NULL..memory corruption\n");return;}    /*從記憶體描述區取出分配時存放的結點指標*/listNode = (t_AMPSSList*)buffDescriptorPtr->dlistNode;memNode = (t_NewMM_MemoryNode*)listNode->pvData;      /*如果此時描述區內標記不為DAED,說明此塊記憶體出錯(例如被覆蓋)*/  if((0 != memcmp(buffDescriptorPtr->markerBytes,"DEAD",4)))      {          printf("FREE: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> marker string not found..memory corruption. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");          return;      }      /*結點為空白,說明已經被釋放*/      if(NULL == listNode)      {          printf("FREE: listNode is NULL: double free or corruption\n");          return;      }    if(NULL == memNode)      {         printf("FREE: memNode is NULL: double free or corruption\n");         return;      }      /*結點已用記憶體數減少釋放的位元組數*/  memNode->nAllocatedBytesInBlock -= buffDescriptorPtr->nSizeOfBuff;      /*如果已用記憶體數為小於0或大於池大小,出錯*/  if(memNode->nAllocatedBytesInBlock < 0 || memNode->nAllocatedBytesInBlock > mmContext->nSizeOfBuff)  {  printf("FREE: allocated bytes = %d, double free or corruption\n",memNode->nAllocatedBytesInBlock);  return;  }  //printf("FREE: mmContext=%p: memNode->nAllocatedBytesInBlock=%d \n", mmContext, memNode->nAllocatedBytesInBlock);      /*如果已用記憶體為0,則釋放這個結點*/  if( 0 == memNode->nAllocatedBytesInBlock)  {  g_nNumFree++;          //printf("Ctxt=%pavailable bytes are 0..freeing memNode %p, total buffers free'd =%d \n",mmContext, memNode, g_nNumFree);  if(listNode == mmContext->poCurrentListPtr)  {  mmContext->poCurrentListPtr = NULL;  }  DList_Remove(&mmContext->memBuffList,listNode,NULL);  free(memNode);  }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.