内存管理
序
你是否好奇过Malloc和Free内部是如何实现?本文为你揭秘。
动态内存管理分为定长内存管理和变成内存管理。定长内存管理每次都分配固定长度内存,算法复杂度是O(1);变长内存管理是申请多少字节就分配多少直接,算法复杂度是O(n)。为了追求时间和空间的平衡,因此本文综合使用定长和变长内存管理。
定长内存管理
void InitFMemory(unsigned char *mem, unsigned int size)
{
int num = 0;
int i = 0;
FMemNode *current = NULL;
FMemNode *next = NULL;
num = size / (sizeof(FMemNode) + F_MEMORY_LENGTH);
gFMemList.listHead = (FMemNode *)mem;
gFMemList.nodeBase = mem;
gFMemList.memBase = mem + num * sizeof(FMemNode);
gFMemList.num = num;
for(i = 0; i < num - 1; i++)
{
current = (FMemNode *)(gFMemList.nodeBase + (sizeof(FMemNode) * i));
next = (FMemNode *)(gFMemList.nodeBase + (sizeof(FMemNode) * (i + 1)));
current->next = next;
}
((FMemNode *)(gFMemList.nodeBase + (sizeof(FMemNode) * i)))->next = NULL;
return;
}
unsigned char* FMalloc()
{
unsigned char *ret = NULL;
unsigned int index = 0;
FMemNode *pos = NULL;
if(NULL != gFMemList.listHead)
{
pos = gFMemList.listHead;
gFMemList.listHead = pos->next;
index = ((unsigned char *)pos - (unsigned char *)(gFMemList.nodeBase)) / sizeof(FMemNode);
ret = (unsigned char *)(gFMemList.memBase) + index * F_MEMORY_LENGTH;
pos->next = (FMemNode *)ret;
}
return ret;
}
int FFree(unsigned char *mem)
{
unsigned int index = 0;
FMemNode *pos = NULL;
index = (mem - gFMemList.memBase) / F_MEMORY_LENGTH;
pos = (FMemNode *)(gFMemList.nodeBase + index * sizeof(FMemNode));
if(mem == (unsigned char *)(pos->next))
{
pos->next = gFMemList.listHead;
gFMemList.listHead = pos;
return 0;
}
return 1;
}
void ShowFMemInfo()
{
FMemNode *pos = gFMemList.listHead;
unsigned int freeNum = 0;
while(NULL != pos)
{
freeNum++;
pos = pos->next;
}
printf("Fix Memory info:\n");
printf("totoal = %d, free = %d\n", gFMemList.num, freeNum);
}
变成内存管理
void InitVmemory(unsigned char *mem, unsigned int size)
{
VMemNode *pNode = NULL;
init_list_head(&gVMemList);
pNode = (VMemNode *)mem;
pNode->freeSize = size;
pNode->UsedSize = 0;
pNode->mem = mem + sizeof(VMemNode);
init_list_head(&pNode->list);
list_add_tail(&pNode->list, &gVMemList);
}
unsigned char* VMalloc(unsigned int size)
{
unsigned char *ret = NULL;
List *pos = NULL;
VMemNode *pNode = NULL;
VMemNode *pNewNode = NULL;
list_for_each(pos, &gVMemList)
{
pNode = (VMemNode *)pos;
if(pNode->freeSize >= (size + sizeof(VMemNode)))
{
pNewNode = (VMemNode *)(pNode->mem + pNode->freeSize + pNode->UsedSize - (size + sizeof(VMemNode)));
pNewNode->freeSize = 0;
pNewNode->UsedSize = size;
pNewNode->mem = (unsigned char*)(pNewNode + 1);
init_list_head(&pNewNode->list);
list_add_tail(&pNewNode->list, pNode->list.next);
pNode->freeSize = pNode->freeSize - (size + sizeof(VMemNode));
ret = pNewNode->mem;
break;
}
}
return ret;
}
void VFree(unsigned char *mem)
{
List *pos = NULL;
VMemNode *pNode = NULL;
VMemNode *pPreNode = NULL;
list_for_each(pos, &gVMemList)
{
pNode = (VMemNode *)pos;
if(pNode->mem == mem)
{
pPreNode = (VMemNode *)(pos->prev);
pPreNode->freeSize = pPreNode->freeSize + pNode->freeSize + pNode->UsedSize + sizeof(VMemNode);
list_del(&pNode->list);
break;
}
}
return;
}
void ShowVMemInfo()
{
List *pos = NULL;
VMemNode *pNode = NULL;
unsigned int num = 0;
printf("Var Memory info:\n");
list_for_each(pos, &gVMemList)
{
pNode = (VMemNode *)pos;
num++;
printf("num = %d, ptr = 0x%x, freeSize = %d, usedSize = %d\n", num, pNode->mem, pNode->freeSize, pNode->UsedSize);
}
return;
}
二者综合使用
void InitMemory(unsigned char *mem, unsigned int size)
{
unsigned char *fmem = NULL;
unsigned char *vmem = NULL;
unsigned int fsize = 0;
unsigned int vsize = 0;
fsize = size / 2;
vsize = size - fsize;
fmem = mem;
vmem = mem + fsize;
InitFMemory(fmem, fsize);
InitVmemory(vmem, vsize);
return;
}
unsigned char* Malloc(unsigned int size)
{
unsigned char *mem = NULL;
if(size <= F_MEMORY_LENGTH)
{
mem = FMalloc();
}
if(NULL == mem)
{
mem = VMalloc(size);
}
return mem;
}
void Free(unsigned char *mem)
{
if(FFree(mem))
{
VFree(mem);
}
return;
}
void ShowMemInfo()
{
printf("-----------Memory Info-----------\n");
ShowFMemInfo();
ShowVMemInfo();
}
测试代码
#include <stdio.h>
#include "memory.h"
int main()
{
unsigned char data[1024 * 1024] = {0};
InitMemory(data, sizeof(data));
unsigned char *p1 = Malloc(20);
unsigned char *p2 = Malloc(200);
unsigned char *p3 = Malloc(16);
ShowMemInfo();
Free(p1);
Free(p2);
Free(p3);
ShowMemInfo();
return 0;
}