01.初识freeRTOS
02.FreeRTOS的移植
03.FreeRTOS系统配置
04.FreeRTOS任务创建与删除
05.FreeRTOS任务挂起与恢复
06.FreeRTOS中断管理
07.FreeRTOS列表与列表项
08.FreeRTOS任务调度与任务切换
09.FreeRTOS时间片调度与任务相关函数
10.FreeRTOS队列操作
11.FreeRTOS信号量操作
12.FreeRTOS队列集和事件标志组
13.FreeRTOS任务通知
14.FreeRTOS软件定时器
15.FreeRTOS低功耗
16.FreeRTOS内存管理
16. FreeRTOS内存管理
1. 内存管理简介
- 创建对象的方法:
- C库内存管理函数的缺点:
2. 内存管理算法
FreeRTOS提供了5种动态内存管理算法,分别为: heap_1
、heap_2
、heap_3
、heap_4
、heap_5
。
如下所示:
算法 | 优点 | 缺点 |
---|---|---|
heap_1 | 分配简单,时间确定 | 只允许申请内存,不允许释放内存 |
heap_2 | 允许申请和释放内存 | 不能合并相邻的空闲内存块会产生碎片、时间不定 |
heap_3 | 直接调用C库函数malloc()和 free() ,简单 | 速度慢、时间不定 |
heap_4 | 相邻空闲内存可合并,减少内存碎片的产生 | 时间不定 |
heap_5 | 能够管理多个非连续内存区域的 heap_4 | 时间不定 |
在我们FreeRTOS例程中,使用的均为heap_4内存管理算法。
-
heap_1
内存管理算法heap_1内存管理算法的分配过程如下图所示:
-
heap_2
内存管理算法特性:
- 可以使用在可能会删除己经创建好的任务、队列、信号量等的应用程序中,但是要注意内存碎片的产生。
- 不应该被使用在多次申请和释放不固定大小内存的情况,因为这可能会导致内存碎片的情况变得严重,例如多次地创建和删除任务、队列等,并且每次创建的任务栈大小、队列长度等都是不固定的,或需要在应用程序中调用函数
pvPortMalloc()
和函数vPortFree()
来申请和释放不固定大小的内存等,以上这些情况都应该慎用heap2内存管理算法。 - 具有不确定性,但是执行的效率比标准C库的内存管理高得多。
最适应算法与内存碎片:
相比于
heap_1
内存管理算法,heap_2
内存管理算法使用最适应算法,并且支持释放内存;heap_2 内存管理算法并不能将相邻的空闲内存块合并成一个大的空闲内存块,因此 heap_2 内存管理算法不可避免地会产生内存碎片;。
-
heap_3
内存管理算法特性:
- 需要链接器提供一个堆,还需要编译器的库提供用于申请内存的函数
malloc()
和用于释放内存的函数free()
。 - 具有不确定性。
- 有可能会大大地增减编译后的代码量。
heap3内存管理算法本质使用的是调用标准C库提供的内存管理函数,标准C库的内存管理需要链接器设置好一个堆,这个堆将作为内存管理的内存堆使用,在启动文件中可以配置这个堆的大小,如下所示:
; 配置堆的大小 Heap_Size EQU 0x00000200 ; AREA: 开辟一段内存空间 ; HEAP: 段名为 HEAP ; NOINIT: 不进行初始化 ; READWRITE: 可读可写 ; ALIGN=3: 以 8(2 的 3 次方)字节对齐 AREA HEAP, NOINIT, READWRITE, ALIGN=3 ; 堆的起始地址 __heap_base ; 分配一个 Heap_Size 大小的内存空间 Heap_Mem SPACE Heap_Size ; 堆的结束地址 __heap_limit
- 需要链接器提供一个堆,还需要编译器的库提供用于申请内存的函数
-
heap_4
内存管理算法特性:
- 适用于在程序中多次创建和删除任务、队列、信号量等的应用。
- 与heap2内存管理算法相比,即使多次分配和释放随机大小的内存,产生内存碎片的几率也要小得多。
- 具有不确定性,但是执行的效率比标准C库的内存管理高得多。
首次适应算法与内存融合:
-
heap_5
内存管理算法heap5内存管理算法是在heap4内存管理算法的基础上实现的,因为heap5内存管理算法使用与heap_4内存管理算法相同的内存分配、释放和合并算法,但是heap_5内存管理算法在heap_4内存管理算法的基础上实现了管理多个非连续内存区域的能力。
3. 内存管理相关API函数
4. 内存管理实验
-
创建任务:
-
任务一:申请内存并释放内存:
void task1(void* pvParamter) { uint8_t key = 0, t = 0, *buf = NULL; while(1) { key = key_scan(0); if(key == KEY0_PRES) { //申请内存 buf = pvPortMalloc(30); if(buf != NULL) { printf("申请内存成功\r\n"); } else{ printf("申请内存失败\r\n"); } } else if(key == KEY1_PRES) { //释放内存 if(buf != NULL) { vPortFree(buf); printf("内存释放\r\n"); } } if(++t > 50) { t = 0; printf("剩余的内存大小为:%d\r\n!", xPortGetFreeHeapSize()); } vTaskDelay(10); } }
-
实验结果: