上一文链接:FreeRTOS笔记(十二)资源管理
01 - 内存管理
回顾一个最开初没有提问的问题,我们创建任务的时候,会生成一个TCB任务控制块,它需要在内存中占据一个空间,多任务中就会有多个TCB,谁给它们分配好空间?谁负责回收空间?一旦空间不够怎么办?
任务需要被内核中不同的函数管理,所以肯定是使用全局变量或者静态变量,于是一个简单的回答是使用全局变量,每创建一个任务就存在一个全局变量,但是任务的创建是动态的,而全局变量的定义是静态的,并不能在系统运行期间再去定义一个全局变量,所以需要提前准备好一些全局变量(全局变量缓存池),当需要的时候就分配,这就是FreeRTOS的内存管理,它不是一个硬件,而是一个软件
由于每一个单板的内存管理都可以不相同,所以FreeRTOS把内存管理归属到可移植层,由实际的情况去编写,同时FreeRTOS提供了若干个内存管理的范例,这些范例是通用的,使用纯C语言编写,与硬件无关,范例中提前准备好的全局变量是一个全局静态数组static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
,在head_x.c(x是数字)中,作用域只能是heap_x.c文件内,生存期是程序开始到结束,所以只能使用pvPortMalloc()
返回ucHeap
中某个位置的地址,使用指针间接访问
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
02 - 范例
查看源码就可以知道每一个范例的内存管理算法、管理方式等,小白使用Sv9.0.0版本的FreeRTOS,提供了5个范例,区别如下
FreeRTOS版本:Sv9.0.0
范例 | 算法 | 分配方式 | 释放方式 | 优点 | 缺点 | 代码量(行) |
---|---|---|---|---|---|---|
head_1.c | 顺序分配,首次适应算法 | 每次都从ucHeap数组中顺序切割 | 无 | 内存分配确定,没有内存碎片 | 内存不可重用 | 185 |
head_2.c | 顺序分配,最佳适应算法 | 每次从空闲链表中找一个大小最合适的内存 | 把释放的内存有序地插入一个从小到大排序的空闲链表 | 内存可重用,分配效率高 | 大块内存得不到分配,相邻的空闲内存不会合并,存在内存碎片 | 314 |
head_3.c | stblib库决定 | 调用了malloc() | 调用了free() | 内存管理由编译器决定 | 代码量可能大大增加,内存分配不确定 | 136 |
head_4.c | 顺序分配,最佳适应算法 | 同head_2.c | 同head_2.c,另外合并相邻的空闲内存 | 同head_2.c,另外限制了内存碎片,相邻空闲内存得到合并 | 大块内存得不到分配 | 477 |
head_5.c | 离散分配 | head_4.c,但是允许跨越不同的内存段 | 同head_4.c | 同head_4.c,另外大块内存得分配 | 分配和释放速度较慢 | 526 |
03 - 总结
- 内存动态分配的本质是在全局变量缓存池中取出全局变量
- 内存碎片越少、使用效率越高,则分配和释放的速度越慢