在资源紧张的单片机系统中,比如几十K的flash空间,如果调用malloc,free等开发环境自带的库函数,往往会占用本来就已经不富裕的存储空间。 例如STM0XX系列单片机,flash空间只有64K, RAM为8K, 使用了malloc, free函数,编译环境为IAR8.3, 最后在map文件看到malloc,free占用将近6K大小的程序段。
基于上述因素,在这实现了一种简单的内存分配机制。基本原理如下:
首先开辟一段全局的数组,做为内存池。 比如2000bytes, gBuf[2000];然后定义一个内存块的大小,比如20bytes;然后定义一个内存块信息数组,每个内阻块对应一个字节,gBufInfo[2000/20]; 标记原则为如果当前的内存块被占用,则在gBufInfo中写入占用的块数, 比如从0位置连续申请了3个内阻块,则gBufInfo[0]=3,gBufInfo[1]=3,gBufInfo[2]=3;
具体代码如下:
#define BUF_TOTAL_SIZE 2000
#define BUF_SIZE 20 // must align 4 bytes
uint8_t gBuf[BUF_TOTAL_SIZE];
uint8_t gBufInfo[BUF_TOTAL_SIZE/BUF_SIZE];
void InitBuf()
{
memset(gBuf, 0, BUF_TOTAL_SIZE);
memset(gBufInfo, 0, sizeof(gBufInfo));
}
void *MallocDef(unsigned short uLen)
{
if (0 == uLen) return NULL;
unsigned char uNeedBufNum = ((uLen-1) / BUF_SIZE) + 1;
unsigned char uEmptyCnt = 0;
unsigned char uStartPos = 0;
unsigned char uBufNum = BUF_TOTAL_SIZE / BUF_SIZE;
for (int i=0; i<uBufNum; i++)
{
if (0 == gBufInfo[i])
{
uEmptyCnt++;
}
else
{
uEmptyCnt = 0;
}
if (uEmptyCnt == uNeedBufNum)
{
uStartPos = i+1-uNeedBufNum;
for (int j=0; j<uNeedBufNum; j++)
{
gBufInfo[uStartPos+j] = uNeedBufNum;
}
return (void*)&gBuf[BUF_SIZE * uStartPos];
}
}
return NULL;
}
void FreeDef(void *pBuf)
{
if (NULL == pBuf) return;
int Pos = (int)pBuf - (int)gBuf;
Pos = Pos / BUF_SIZE;
if (Pos >= (BUF_TOTAL_SIZE / BUF_SIZE)) return;
unsigned char uUseBufNum = gBufInfo[Pos];
for (int i=0; i<uUseBufNum; i++)
{
gBufInfo[Pos + i] = 0;
}
}
unsigned short CalcFreeBufNum()
{
unsigned char uBufNum = BUF_TOTAL_SIZE / BUF_SIZE;
unsigned char uNum = 0;
for (int i=0; i<uBufNum; i++)
{
if (0 == gBufInfo[i])
{
uNum++;
}
}
return uNum;
}
优点: 代码简单小巧,原理简单。
缺点:一个内阻块的空间无法百分百的利用, 比如申请5个字节内存,则同样会占用一个内阻块20字节。
搜索空余内存块采用遍历方式,如果内存块较多则搜索时间变成长, 但对于单片机系统几百个内阻块来说,时间上
不存在问题。
总结: 只选对的,不选贵的。