Freertos定义了一个很大的全局数组ucHeap[configTOTAL_HEAP_SIZE],从这个数组里分配内存;下图是创建三个任务的过程;
有五种内存管理机制;
heap_1.c:只分配不删除,只有pvPortMalloc,没有实现vPortFree;
heap_2.c:最佳匹配算法,但不会合并相邻的空闲内存,碎片化严重;
假设heap有3块空闲内存:5字节、25字节、100字节,pvPortMalloc想申请20字节,找出最小的、能满足pvPortMalloc的内存:25字节,把它划分为20字节、5字节;
A:创建了3个任务
B:删除了一个任务,空闲内存有3部分:顶层的、被删除任务的TCB空间、被删除任务的Stack空间
C:创建了一个新任务,因为TCB、栈大小跟前面被删除任务的TCB、栈大小一致,所以刚好分配 到原来的内存
heap_3.c:使用标准C库里的malloc、free函数,configTOTAL_HEAP_SIZE不再起作用;
注:C库里的malloc、free函数并非线程安全的,Heap_3中先暂停FreeRTOS的调度器,再去调用这些函数,使用这种方法实现了线程安全。
heap_4.c:首次适应算法,会把相邻空闲内存合并为一个大的空闲内存,可以较少内存的碎片化;
假设堆中有3块空闲内存:5字节、200字节、100字节,pvPortMalloc想申请20字节,找出第1个能满足pvPortMalloc的内存:200字节,把它划分为20字节、180字节
A:创建了3个任务
B:删除了一个任务,空闲内存有2部分:顶层的被删除任务的TCB空间、被删除任务的Stack空间合并起来的
C:分配了一个Queue,从第1个空闲块中分配空间
D:分配了一个User数据,从Queue之后的空闲块中分配
E:释放的Queue,User前后都有一块空闲内存
F:释放了User数据,User前后的内存、User本身占据的内存,合并为一个大的空闲内存
heap_5.c:Heap_5分配内存、释放内存的算法跟Heap_4是一样的,不局限于管理一个大数组:它可以管理多块、分隔开的内存。