当前位置: 首页 > 工具软件 > AMPS > 使用案例 >

AMPS:内存管理模块源码解读(二)

章宏峻
2023-12-01

  上节看了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" {
#endif


typedef 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=%p	allocated 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=%p	available 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);

	  }
}



 类似资料: