内存管理
1. FreeRTOS为什么要实现自己的内存管理
内存的动态管理是C语言程序的知识范围,并不属于FreeRTOS的知识范畴,但是它跟FreeRTOS关系是如此紧密。
在C语言的库函数中,有mallc、free等函数,但是在FreeRTOS中,它们不适用:
- 不适合用在资源紧缺的嵌入式系统中
- 这些函数的实现过于复杂、占据的代码空间太大
- 并非线程安全的(thread-safe)
- 运行有不确定性:每次调用这些函数时花费的时间可能都不相同
- 内存碎片化
- 使用不同的编译器时,需要进行复杂的配置
- 有时候难以调试
注意:“堆栈”混着说,但是并不是同一个东西
- 堆,heap,就是一块空闲的内存,需要提供管理函数。
- malloc:从堆里划出一块空间给程序使用。
- free:用完后,再把它标记为“空闲”的,可以再次使用。
- 栈,stack,函数调用时局部变量保存在栈中,当前程序的环境也是保存在栈中
- 可以从堆中分配一块空间用作栈
2. FreeRTOS的5种内存管理方法
FreeRTOS中内存管理的接口函数为:pvPortMalloc、vPortFree,对应于C库的malloc、free。
文件在 FreeRTOS/Source/portable/MemMang
下,它也是放在 portable
目录下,表示你可以提供自己的函数。
源码中默认提供了5个文件,对应内存管理的5种方法。
文件 | 优点 | 缺点 |
---|---|---|
heap_1.c | 分配简单,时间确定 | 只分配、不回收 |
heap_2.c | 动态分配、最佳匹配 | 碎片、时间不定 |
heap_3.c | 调用标准库函数 | 速度慢、时间不定 |
heap_4.c | 相邻空闲内存可合并 | 可解决碎片问题、时间不定 |
heap_5.c | 在heap_4基础上支持分隔的内存块 | 可解决碎片问题、时间不定 |
2.1 heap_1.c
它只实现了pvPortMalloc,没有实现vPortFree。
如果你的程序不需要删除内核对象,那么可以使用heap_1:
- 实现最简单
- 没有碎片问题
- 一些要求非常严格的系统里,不允许使用动态内存,就可以使用heap_1
它的实现原理很简单,首先定义一个大数组:
/* Allocate the memory for the heap. */
##if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
/* The application writer has already defined the array used for the RTOS
* heap - probably so it can be placed in a special segment or address. */
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
##else
static uint8_t ucH