FreeRtos进阶——各种堆的实现方式

堆介绍

"堆"就是一块或者多块内存,我们可以从中申请一小块内存来使用,使用完毕后可以释放这一小块内存。

  • 使用malloc函数从中申请、获得一小块内存
  • 使用free函数释放这一小块内存
  • 这些malloc、free函数就是用来管理这些内存的
  • malloc、free函数可以有其他名称,比如FreeRTOS里是pvPortMalloc、vPortFree

堆内存来源

在汇编代码里指定一个AREA:在汇编代码里,使用SPACE命令可以分配一段空间
在这里插入图片描述
在FreeRtos的C代码里,定义一个全局数组作为操作系统的堆来使用:
在这里插入图片描述

heap_1实现方式

heap_1.c里,只实现了pvPortMalloc函数,vPortFree函数并未实现。
初始状态
在这里插入图片描述分配内存
在这里插入图片描述
在heap_1中,pucAlignedHeap代表堆的起始地址,xNextFreeByte代表偏移地址,当申请了一段空间后,偏移地址的值也会随之增加。因此,可以用空间的起始地址为:起始地址加上偏移地址。

heap_2实现方式

heap_2.c里,使用链表来管理内存。链表结构体为:
在这里插入图片描述
这个结构体用来表示空闲块:

  • pxNextFreeBlock:指向下一个空闲块

  • xBlockSize:当前空闲块的内存大小
    这个结构体后面,紧跟着空闲内存,如下图所示:
    在这里插入图片描述
    初始状态

  • 链表头:xStart,指向第1个FreeBlock

  • 第1个FreeBlock:从pucAlignedHeap开始,它的xBlockSize等于configADJUSTED_HEAP_SIZE,表示整个堆的大小

  • 链表尾:xEnd,它的xBlockSize也是configADJUSTED_HEAP_SIZE,xEnd并没有对应的空闲内存,这个值只是为了排序
    在这里插入图片描述
    分配内存
    void * pvPortMalloc( size_t xWantedSize )的内部实现:

  • 调整xWantedSize:加上sizeof(struct BlockLink_t),向上对齐。

  • 从xStart开始寻找第1个大小合适FreeBlock:这个FreeBlock的xBlockSize >= xWantedSize

  • 把这个FreeBlock从链表中删除

  • 如果这个FreeBlock的xBlockSize 比较大,把它拆分成2个Block

    • 第1个Block被占用,大小为xWantedSize
    • 第2个Block是空闲的,还要放入链表:按照xBlockSize从小到大的顺序插入链表
  • 返回的地址如下图所示:

堆字节对齐,如果是八字节对齐,那么如果申请100字节的空间是不行的,要找到大于100字节的被8整除的最小字节数,103才可以。同样的堆的起始地址有时候并不满足8字节对齐,所以为了满足字节对齐的要求,我们必须将起始地址向后偏移,才是真正的起始地址。

在这里插入图片描述
分配结果如下图所示:
在这里插入图片描述
释放内存

void vPortFree( void * pv )函数:

  • 根据pv往前移动,得到BlockLink_t结构体
  • 把这个结构体放入xStart链表:按照xBlockSize从小到大的顺序插入链表

heap_4实现方式

heap_4的链表结构跟heap_2一样,最大的区别在于实现相邻内存块的合并。
初始状态

  • 链表头:xStart,它是一个BlockLink_t结构体,是链表中第1个元素
  • 第1个FreeBlock:从pucAlignedHeap开始,它的xBlockSize等于Block的大小,表示整个堆的大小(除去尾部)
  • 链表尾:xEnd,它是BlockLink_t指针,指向空闲内存的尾部
    在这里插入图片描述

分配内存
内存分配方式与heap_2一模一样,没有区别。

释放内存
void vPortFree( void * pv )函数:

  • 根据pv往前移动,得到BlockLink_t结构体
  • 把这个结构体放入xStart链表:按照Block地址从小到大的顺序插入链表
  • 并且:尝试合并相邻的Block

heap_5实现方式

heap_5支持分隔的内存块,heap_4只支持单一的内存块。
heap_5和heap_4的代码几乎一样,只是在初始化函数方面有差别:

  • heap_4:在第1次调用pvPortMalloc时,使用prvHeapInit进行初始化
  • heap_5:在使用pvPortMalloc之前,需要先调用vPortDefineHeapRegions指定内存区域

heap_5和heap_4,它们的pvPortMallocvPortFree,函数代码时完全一样的。

初始化
HeapRegion结构体示意图在这里插入图片描述
初始化多个内存块方法
在这里插入图片描述
初始化多个内存块结束后,链表大概的长这样
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值