内存管理
内存通常分为两种:内部存储空间(RAM
)和外部存储空间(硬盘)
避免使用C
语言标准库的malloc
和free
内存函数
- 嵌入式
RAM
可能不足,函数并不总是可用 - 实现可能很大,占用很大的代码空间
- 几乎不安全
- 调用时间不确定,每次可能都不一样
- 可能产生碎片
- 会使链接器配置复杂
- 如果允许堆空间的生长方向覆盖其他变量占据的内存,会成为
debug
的灾难
内存管理应用场景
void *pvPortMalloc(size_t xSize)
申请内存void vPortFree(void *pv)
释放内存void vPortInitialiseBlocks(void)
初始化内存堆size_t xPortGetFreeHeapSize(void)
获取当前未分配的内存堆大小size_t xPortGetMinimumEverFreeHeapSize(void)
获取未分配的内存堆历史最小值heap_1.c
、heap_2.c
、heap_4.c
内存堆是一个很大的数组heap_3.c
是使用C
语言原生的malloc
和free
函数,但是进行的安全保护的封装,需要用户通过编译器或者启动文件设置空间heap_5.c
允许用户使用多个非连续的内存堆空间,同时可以使用外部SDRAM、内存卡等
heap_1
- 用于从不删除任务、队列、信号量、互斥量等应用程序
- 函数执行时间是确定并且不会产生内存碎片
- 不支持释放内存
heap_2
- 和
heap_1
的内存管理算法不同,采用最佳匹配算法,支持释放内存不能将相邻的小碎片内存合并为大内存 - 可用于反复删除任务、队列、信号量、互斥量等内核对象且不担心内存碎片的应用程序
- 若存在一些碎片化的任务,那么可能导致内存碎片
- 具有不确定性,但是比
C
语言原生的malloc
高级 - 不能用于内存分配和释放是随机大小的应用程序
heap_3
- 简单封装
C
语言的malloc
和free
,满足常用的编译器,具有保护功能 - 需要链接器设置一个堆,
malloc
和free
由编译器提供 - 具有不确定性
- 很可能增大
RTOS
内核代码大小 configTOTAL_HEAP_SIZE
宏定义不起作用
heap_4
- 在
heap_2
的基础上加上了合并算法,能将相邻空闲内存合并为1个更大的块 - 可用于重复删除任务、队列、信号量、互斥量等的应用程序
- 可用于分配和释放随机字节内存的应用程序,但并不像
heap_2
那样产生严重的内存碎片 - 具有不确定性,但是效率比
C
语言原生的malloc
函数高
heap_5
- 动态分配和
heap_4
是一样,采用最佳匹配和合并算法,并且允许内存跨多个非连续内存区 - 需要使用
vPortDefineHeapRegions()
来实现内存初始化
创建内存管理
内存管理句柄,创建一个引用,并不是创建一个真实的内存管理
1 | //内存管理 |
Test任务
1 | //内存管理 |
按下
BTN1
申请内存,并将系统当前TickCount
打印,按下BTN2
释放内存