【FreeRTOS】内存管理

FreeRTOS内存管理

FreeRTOS创建任务、队列、信号量等数据需要内存时,有两种内存创建方法:一时动态申请所需的RAM,二是静态申请所需RAM,一般使用静态创建内存的函数名结尾带有"Static"。

在标准C库中提供了malloc()和free()函数来实现动态内存管理,但由于部分原因限制使用:

  • 在小型的嵌入式系统中效率不高
  • 会占用很多的代码空间
  • 不是线程安全
  • 会导致内存碎片
  • 使链接器的配置变得复杂

因此FreeRTOS的内存管理方法中提供了pvPortMalloc()来替代malloc()申请内存,vPortFree()函数来替代free()释放内存。

FreeRTOS提供了5种内存分配方法,使用FreeRTOS时任选其一即可,分别是:heap_1.c、heap_2.c、heap_3.c、heap_4.c、heap_5.c,这5个文件再FreeRTOS源码中,路径:FreeRTOS->Source->portable->MemMang中。

动态内存分配需要一个内存堆,在FreeRTOS中内存堆为ucHeap[],大小为configTOTAL_HEAP_SIZE。不管是哪种内存分配方法,它们的内存堆都为ucHeap[],而且大小都为configTOTAL_HEAP_SIZE,内存堆在文件heap_x.c(x为1-5)中定义,比如heap_1.c文件中有如下定义:

#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; //需要用户自行定义内存堆
#else
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; //编译器决定
#endif

宏configAPPLICATION_ALLOCATED_HEAP为1时由用户自行定义内存堆,否则有编译器决定,默认都是编译器决定。

内存碎片

内存堆在经过多次申请和释放后,会产生很多内存很小的内存块,这些内存卡地址不连续,无法重新申请使用,这种内存块就叫内存碎片。

heap_1内存分配方法

特性:

  1. 适用于一旦创建好任务、信号量和队列就不在删除的应用
  2. 具有可确定性(执行所华花费的时间大多数都是一样的),而且不会导致内存碎片(因为heap_1算法无法处理内存碎片)
  3. 代码实现和内存分配过程非常简单,内存是从一个静态数组中分配到的,也就是适合于不需要动态分配内存的应用

heap_1算法没有提供内存释放函数

heap_2内存分配方法

其实与heap_1算法差不多一致,唯一的区别就是多了内存释放函数,通过引入内存块的概念和一个链表结构,来实现内存释放,该链表结构包含当前内存块的大小和指向链表中下一个空闲内存块。

特性:

  1. 可以使用在需要重复申请释放内存的应用,但是会产生内存碎片
  2. 具有不可确定性,但远比标准C中的malloc()和free()效率高

heap_3内存分配方法

特性:

  1. 需要编译器提供一个内存堆,编译器库要提供malloc()和free()函数,比如使用STM32的话可以通过修改启动文件中的Heap_Size来修改内存堆的大小
  2. 具有不确定性
  3. 可能会增加代码量(因为内部其实是调用malloc和free)

heap_3其实就是对标准C库中的malloc和free进行了简单的封装,所以才需要编译器库提供两个函数,也才会导致代码量增加

heap_4内存分配方法(常用)

heap_4其实是在heap_2的基础上进一步优化,依然使用和heap_2一样的链表结构,并额外定义两个局部静态变量xStart和pxEnd来表示链表头和尾

特性:

  1. 可以用在需要重复申请释放内存的应用中
  2. 不会产生严重的内存碎片,即使分配的内存大小是随机的
  3. 具有不确定性,但远比标准C中的malloc()和free()效率高

heap_5内存分配方法

heap_5使用了和heap_4相同的合并算法,内存管理实现起来基本相同,但是heap_5运行内存堆跨越多个不连续的内存段,比如 STM32 的内部 RAM 可以作为内存堆,但是 STM32 内
部 RAM 比较小,遇到那些需要大容量 RAM 的应用就不行了,如音视频处理。不过 STM32 可
以外接 SRAM 甚至大容量的 SDRAM,如果使用 heap_4 的话你就只能在内部 RAM 和外部
SRAM 或 SDRAM 之间二选一了,使用 heap_5 的话就不存在这个问题,两个都可以一起作为
内存堆来用。

如果使用 heap_5 的话,在调用 API 函数之前需要先调用函数 vPortDefineHeapRegions ()来
对内存堆做初始化处理,在 vPortDefineHeapRegions()未执行完之前禁止调用任何可能会调用
pvPortMalloc()的 API 函数!

总结

heap_1最简单,但是只有内存申请函数,没有内存释放函数

heap_2在heap_1的基础上多了内存释放函数

heap_3只是对标准C库中的malloc和free进行封装,并提供了线程保护

heap_4在heap_2的基础上对内存碎片进行了处理

heap_5在heap_4的基础上实现对不连续内存堆的应用

内存管理实验

在做内存管理实验时,通过pvPortMalloc(30)申请了30个字节的内存空间,在申请前通过xPortGetFreeHeapSize()获取的剩余内存为7136,申请后发现变成了7096,说明申请了40个字节的内存,但实际上只申请了30,这是因为除开所申请的30字节内存外,还要加上结构体BlockLink_t的大小然后做8字节对齐后导致的多申请了10字节内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值