FreeRTOS内存管理简介
在使用FreeRTOS创建任务,队列,信号量等对象时,一般都提供两种方法
- 1:动态创建任务(方法)自动地从FreeRTOS管理的内存堆中申请创建对象所需要的内存,并且在删除对象后可以将这块内存释放回FreeRTOS管理的内存堆。
- 2:需要用户提供各种内存空间,并且使用静态方式占用内存空间一般是固定的,即使任务,队列等被删除后,这些被占用的内存空间一般没有其他用途。
注:
- 1:动态方式管理内存相比于静态方式更为灵活
- 2:除了FreeRTOS提供的动态内存管理方法,标准的C库也提供了函数malloc()和函数free()来实现动态地申请和释放内存。
使用c语言标准库动态内存管理的缺点
- 1:占用大量的代码空间不适合用在资源紧缺的嵌入式系统中
- 2:没有线程安全的相关机制
- 3:运行有不确定性,每次调用这些函数时花费的时间可能都不相同
- 4:内存碎片化
FreeRTOS提供多种动态内存管理算法,可以针对不同的嵌入式系统
FreeRTOS内存管理算法(熟悉)
FreeRTOS提供了5种动态内存管理算法,分别为: heap 1、heap 2、heap 3、heap 4、heap 5。
(主要使用的是heap_4内存管理算法)。
如下所示:
haep_1 内存管理算法
heap_1只实现了pvPortMalloc,没有实现vPortFree;也就是说,它只能申请内存,无法释放内存!如果你的工程,创建好的任务、队列、信号量等都不需要被删除,那么可以使用heap_1内存管理算法heap_l的实现最为简单,管理的内存堆是一个数组}在申请内存的时候,heap_1内存管理算法只是简单地从数组中分出合适大小的内存,内存堆数组的定义如下所示。
/*定义一个数组作为FreeRTOS管理的内存堆*/
static uint8_t ucHeap[configTOTAL_HEAP_SIZE];
heap_1内存管理算法的分配过程
heap_2 内存管理算法
相比于heap_l内存管理算法,heap_2内存管理算法使用最适应算法,并且支持释放内存;
heap_2内存管理算法并不能将相邻的空闲内存块合并成一个大的空闲内存块;因此 heap_2内存管理算法不可避免地会产生内存碎片;
最适应算法:
假设heap有3块空闲内存(按内存块大小由小到大排序)︰5字节、25字节、50字节
现在新创建一个任务需要申请20字节的内存
第一步:找出最小的、能满足pvPortMalloc的内存:25字节
第二步:把它划分的20字节、5字节;返回这20字节的地址,剩下的5字节仍然是空闲状态,留给后续的pvPortMalloc使用!
注:内存碎片是由于多次申请和释放内存,但释放的内存无法与相邻的空闲内存合并而产生的。
适用场景:频繁的创建和删除任务,且所创建的任务队都是相同的
heap_4内存管理算法
heap_4内存管理算法使用了首次适应算法,也支持内存的申请与释放,并且能够将空闲且相邻的内存进行合并,从而减少内存碎片的现象。
首次适应算法:
假设heap有3块空闲内存(按内存块地址由低到高排序)︰5字节、50字节、25字节
现在新创建一个任务需要申请20字节的内存
第一步:找出第一个能满足pvPortMalloc的内存:50字节
第二步∶把它划分为20字节、30字节;返回这20字节的地址,剩下30字节仍然是空闲状态,留给后续的pvPortMalloc使用!
适用场景,频繁的释放,分配不同大小的内存
heap_5内存管理算法
heap_5内存管理算法是在heap_4内存管理算法的基础上实现的,但是heap_5内存管理算法在 heap_4内存管理算法的基础上实现了管理多个非连续内存区域的能力
heap_5内存管理算法默认并没有定义内存堆,需要用户手动指定内存区域的信息,对其进行初始化。
内存管理算法5的结构体:
typedef struct HeapRegion{
/*内存区域起始地址*/
uint8_t * putStartAddress;
/*内存区域的大小,单位:字节*/
size_t xSizeInBytes;
}HeapRegion_t;
Heap_5内存管理算法指定多块不连续的内存
Const HeapRegion_t xHeapRegions[] = {
{(uint8_t*)0x80000000,0x10000} /*内存区域1*/
{(uint8_t*)0x90000000,0x10000} /*内存区域2*/
};
vPortDefineHeapRegions(xHeapRegions);
FreeRTOS相关API函数解析
FreeRTOS内存管理实验
【后续会继续完善更新.....】