FreeRtos核心功能
内存管理
FreeRtos内存管理函数有两种,分别是pvPortMalloc以及vPortFree,对应于C语言的malloc和free函数。
源码中对应5个文件,对应内存管理的5个方法。
碎片化问题介绍
五种内存管理方法
Heap_1
Heap_1只执行pvPortMalloc函数,不执行vPortFree函数。若程序不需要释放内核对象,则可以使用Heap_1。
实现原理:定义一个大数组,调用pvPortMalloc函数时,从数组中分配空间。
示例
Heap_2
Heap_2可以执行pvPortMalloc函数和vPortFree函数。
Heap_2也是在数组上分配内存空间,Heap_2函数使用最佳匹配算法来分配内存空间。
最佳匹配算法:假设 heap 有 3 块空闲内存:5 字节、25 字节、100 字节,pvPortMalloc 想申请 20 字节,找出最小的、能满足 pvPortMalloc 的内存:25 字节,把它划分为 20 字节、5 字节,返回这 20 字节的地址,剩下的 5 字节仍然是空闲状态,留给后续的 pvPortMalloc 使用。
Heap_2的缺点是不会合并相邻的空闲内存,造成“碎片化”问题。
示例
该示例新任务的Stack和TCB的大小和前面被删除任务的Stack和TCB的大小一致,所以刚好分配到原来的内存。
Heap_3
Heap_3用于调用标准库函数。
Heap_4
Heap_4可以执行pvPortMalloc函数和vPortFree函数。
Heap_4也是在数组上分配内存空间,Heap_4函数使用首次适应算法来分配内存空间。它还会把相邻的空闲内存合并为一个更 大的空闲内存,这有助于较少内存的碎片问题。
首次适应算法:假设堆中有 3 块空闲内存:5 字节、200 字节、100 字节,pvPortMalloc 想申请 20 字节,找出第 1 个能满足 pvPortMalloc 的内存即200 字节,把它划分为 20 字节、180 字节,返回这 20 字节的地址,剩下的 180 字节仍然是空闲状态,留给后续的 pvPortMalloc 使用。
示例
创建了 3 个任务。删除了一个任务,空闲内存有 2 部分:顶层的以及被删除任务的 TCB 空间、被删除任务的 Stack 空间合并起来的。分配了一个 Queue,从第 1 个空闲块中分配空间,分配了一个 User 数据,从 Queue 之后的空闲块中分配。释放的 Queue,User 前后都有一块空闲内存,释放了 User 数据,User 前后的内存、User 本身占据的内存,合并为一个大的内存空间。
Heap_5
Heap_5 分配内存、释放内存的算法跟 Heap_4 是一样的。相比于Heap_4,Heap_5并不局限于管理一个大数组:它可以管理多块、分隔开的内存。在嵌入式系统中,内存的地址可能并不连续,这种场景下可以使用Heap_5。
既然内存是分散开的,那就要指定内存的起始位置和内存大小。在使用pvPortMalloc函数之前用函数vPortDefineHeapRegions 来指定这些信息。
指定一块内存,使用如下结构体指定起始位置和大小
typedef struct HeapRegion
{
uint8_t *pucStartAddress; //起始位置
size_t xSizeInBytes; //大小
} HeapRegion_t;
指定多块内存,使用数组HeapRegion_t,低地址在前、高地址在后。
HeapRegion_t xHeapRegions[] =
{
{ ( uint8_t * ) 0x80000000UL, 0x10000 }, //起始地址0x80000000 大小0x10000
{ ( uint8_t * ) 0x90000000UL, 0xa0000 }, //起始地址0x90000000 大小0xa0000
{ NULL, 0 } //表示数组结束
};
vPortDefineHeapRegions函数原型如下:把 xHeapRegions 数组传给 vPortDefineHeapRegions 函数,即可初始化 Heap_5。
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions );
Heap相关函数
1.void * pvPortMalloc( size_t xWantedSize );
2.void vPortFree( void * pv );
作用:分配内存、释放内存。如果分配内存不成功,则返回值为NULL。
3.size_t xPortGetFreeHeapSize( void );
作用:当前还有多少空闲内存,函数可以用来优化内存的使用情况。
注意:在heap_3中无法使用。
4.size_t xPortGetMinimumEverFreeHeapSize( void );
作用:程序运行过程中空闲内存容量的最小值。
注意:只有heap_4、heap_5支持此函数。
5.malloc 失败的钩子函数
如果想使用这个钩子函数:
在 FreeRTOSConfig.h 中,把 configUSE_MALLOC_FAILED_HOOK 定义为 1。
提供 vApplicationMallocFailedHook 函数。
pvPortMalloc 失败时,才会调用此函数。