上节看了AMPS中通过数组+单链表实现的内存池,本节看看另一个实现方式。此方法思路如下:其内存池结构为一个存放已分配内存信息的双链表,一个表示内存池大小的变量,一个指向当前内存链表结点的指针链表,如下:
/*内存池结构*/
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;/*存放已分配的内存结点指针*/
};
下面看看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);
}
}