Free RTOS:内存管理
目录1.为什么要自己实现内存管理在C语言的库函数中有mallc、free等函数但是在FreeRTOS中它们不适用注意我们经常堆栈混合着说其实它们不是同一个东西2.FreeRTOS 的 5 中内存管理方法5个内存管理方法2.1 Heap_1如果你的程序不需要删除内核对象那么可以使用heap_1它的实现原理很简单首先定义一个大数组2.2 Heap_2Heap_2也是在数组上分配内存跟Heap_1不一样的地方在于使用heap_2时内存分配过程如下图所示2.3 Heap_32.4 Heap_4首次适应算法Heap_4的使用过程举例如下2.5 Heap_5vPortDefineHeapRegions函数原型如下3.Heap 相关的函数3.1 pvPortMalloc/vPortFree函数原型3.2 xPortGetFreeHeapSize函数原型3.3 xPortGetMinimumEverFreeHeapSize函数原型3.4 malloc 失败的钩子函数在 pvPortMalloc 函数内部所以如果想使用这个钩子函数4.STM32CubeMX堆的配置1.为什么要自己实现内存管理后续的章节涉及这些内核对象task、queue、semaphores和event group等。为了让FreeRTOS更容易使用这些内核对象一般都是动态分配用到时分配不使用时释放。使用内存的动态管理功能简化了程序设计不再需要小心翼翼地提前规划各类对象简化API函数的涉及甚至可以减少内存的使用内存的动态管理是C程序的知识范畴并不属于FreeRTOS的知识范畴但是它跟FreeRTOS关系是如此紧密所以我们先讲解它在C语言的库函数中有mallc、free等函数但是在FreeRTOS中它们不适用注意我们经常堆栈混合着说其实它们不是同一个东西2.FreeRTOS 的 5 中内存管理方法FreeRTOS中内存管理的接口函数为pvPortMalloc 、vPortFree对应于C库的malloc、free文件在FreeRTOS/Source/portable/MemMang下它也是放在portable目录下表示你可以提供自己的函数源码中默认提供了5个文件对应内存管理的5种方法参考文章5个内存管理方法2.1 Heap_1Heap_1比Heap_2更少用到它只实现了pvPortMalloc没有实现vPortFree如果你的程序不需要删除内核对象那么可以使用heap_1它的实现原理很简单首先定义一个大数组然后对于 pvPortMalloc 调用时从这个数组中分配空间FreeRTOS在创建任务时需要2个内核对象task control block(TCB)、stack。 使用heap_1时内存分配过程如下图所示2.2 Heap_2Heap_2很少用到Heap_2之所以还保留只是为了兼容以前的代码。新设计中不再推荐使用Heap_2。建议使用Heap_4来替代Heap_2更加高效Heap_2也是在数组上分配内存跟Heap_1不一样的地方在于与Heap_4相比Heap_2不会合并相邻的空闲内存所以Heap_2会导致严重的碎片化问题但是如果申请、分配内存时大小总是相同的这类场景下Heap_2没有碎片化的问题。所以它适合这种场景频繁地创建、删除任务但是任务的栈大小都是相同的(创建任务时需要分配TCB和栈TCB总是一样的)虽然不再推荐使用heap_2但是它的效率还是远高于malloc、free使用heap_2时内存分配过程如下图所示2.3 Heap_3一般不用Heap_3Heap_3 使用标准 C 库里的 malloc、free 函数所以堆大小由链接器的配置决定配置项 configTOTAL_HEAP_SIZE 不再起作用C库里的malloc、free函数并非线程安全的Heap_3中先暂停FreeRTOS的调度器再去调用这些函数使用这种方法实现了线程安全2.4 Heap_4一般使用这Heap_4跟 Heap_1、Heap_2 一样Heap_4 也是使用大数组来分配内存Heap_4使用首次适应算法(first fit)来分配内存。它还会把相邻的空闲内存合并为一个更大的空闲内存这有助于较少内存的碎片问题首次适应算法Heap_4会把相邻空闲内存合并为一个大的空闲内存可以较少内存的碎片化问题。适用于这种场景频繁地分配、释放不同大小的内存Heap_4的使用过程举例如下Heap_4执行的时间是不确定的但是它的效率高于标准库的malloc、free2.5 Heap_5有多块内存就使用这个Heap_5Heap_5 分配内存、释放内存的算法跟 Heap_4 是一样的相比于Heap_4Heap_5并不局限于管理一个大数组它可以管理多块、分隔开的内存在嵌入式系统中内存的地址可能并不连续这种场景下可以使用Heap_5既然内存时分隔开的那么就需要进行初始化确定这些内存块在哪、多大怎么指定一块内存使用如下结构体怎么指定多块内存使用一个HeapRegion_t数组在这个数组中低地址在前、高地址在后比如这里数组里每一项都表示一个内存块“起始地址、大小”最后一项为0vPortDefineHeapRegions函数原型如下把 xHeapRegions 数组传给 vPortDefineHeapRegions 函数即可初始化 Heap_53.Heap 相关的函数3.1 pvPortMalloc/vPortFree函数原型作用分配内存、释放内存如果分配内存不成功则返回值为NULL3.2 xPortGetFreeHeapSize函数原型当前还有多少空闲内存这函数可以用来优化内存的使用情况。比如当所有内核对象都分配好后执行此函数返回 2000那么 configTOTAL_HEAP_SIZE 就可减小 2000注意在heap_3中无法使用3.3 xPortGetMinimumEverFreeHeapSize函数原型返回程序运行过程中空闲内存容量的最小值注意只有heap_4、heap_5支持此函数3.4 malloc 失败的钩子函数在 pvPortMalloc 函数内部所以如果想使用这个钩子函数4.STM32CubeMX堆的配置