MCU内存管理的一个想法(碎片整理的可行性)
前几天捣鼓了下MCU的内存管理,自己用链表实现了一个。相同思路的程序网上一抓一大把。但是找了一圈都没有发现能实现碎片整理。尽管MCU上内存管理就不常用,还用到碎片整理的基本没有。但是用不用是一码事,能不能是另一码事。
这篇文章只是我的一些想法和思路,可能思考的不全面且并未实践过,不保证实际可行性。
要能实现碎片回收要做到两件事。
1:空闲内存的查找,内存数据的移动。
2:内存移动后,原来的应用程序还能定位到它。
第1点不难,之前的内存管理方法都能实现。第2点是关键。正常的malloc程序,都是返回一个地址给应用程序,一旦内存被移动,那如果应用程序还根据原来的地址找内存就不对了。
所以我想找一个不会变的标志替代指针返回给应用程序。
typedef struct node
{
u32 linkid;//内存块id ,替代指针,返回给应用程序 0表示失败。
u32 offset; //与内存首地址的偏移
u32 size;//本节点带的内存大小
PNode Prior;//前一节点
PNode Pnext;//后一节点
}Node;
如上,在节点中引入一个id。该id在malloc阶段生成,并返回给应用程序,应用程序每次使用内存前,要遍历链表找到对应id的节点,该节点后的内存就是应用程序能用的内存。这样碎片整理进行内存移动时,只要保证本节点中的id不变,应用程序就能找到内存地址。伪代码逻辑如下。
// u32 malloc(size);
//void *GetMenaddr(id)
//void free(id)
u32 id = malloc(1024);
u8 *p1 ;
p1= (u8*)GetMenaddr(id);
/*
.......
*/
u8 *p2 ;
p2= (u8*)GetMenaddr(id);
/*
.......
*/
free(id);
但是上述方式如果在内存被任务程序使用过程中,任务程序被打断进入内存整理,然后返回继续执行任务程序。这样就会有问题。因为在GetMenaddr后,应用程序处理的就是指针。如果被中断进性内存整理,那指针所指的数据就已经被搬移。因此还要做一些处理。
typedef struct node
{
u32 linkid;//内存块id ,替代指针,返回给应用程序
u32 state; //状态 内存是否锁定。
u32 offset; //与内存首地址的偏移
u32 size;//本节点带的内存大小
PNode Prior;//前一节点
PNode Pnext;//后一节点
}Node;
加入一个锁定标志,碎片整理程序先判断该节点的内存是否是被锁定的,是的话就不对该节点进性整理。伪代码逻辑如下。
// u32 malloc(size);
//void MenLock(id);
//void *GetMenaddr(id)
//void MenUnlock(id);
//void *GetMenaddr(id)
//void free(id)
u32 id = malloc(1024);
MenLock(id);
u8 *p1 ;
p1= (u8*)GetMenaddr(id);
/*
.......
*/
MenUnlock(id);
//这之后允许碎片整理任务整理该id对应的内存
/*
...
*/
MenLock(id);
u8 *p2 ;
p2= (u8*)GetMenaddr(id);
/*
.......
*/
MenUnlock(id);
free(id);
以上就是对碎片整理时内存处理方式的思考,应该还有一些问题没解决,先这样!