freeRTOS源码中提供了五种内存管理的方案,可以说是很方便了。实际需要使用哪一种,可以根据自己项目的需要进行选择,都是可以的。
那这五种不同的内存管理方式都有哪些差异呢?按照官方给出的说明,这五种内存管理的特点分别如下:
1、内存管理方式 1(heap_1.c)
heap_1 动态内存管理方式是五种动态内存管理方式中最简单的,这种方式的动态内存管理一旦申请 了相应内存后,是不允许被释放的。
尽管如此,这种方式的动态内存管理还是可以满足许多的嵌入式项目的, 因为有些嵌入式产品在系统启动阶段就明确了任务创建、事件标志组、信号量、消息队列等资源的使用情况, 而且这些资源是整个运行过程中都要一直使用的,并不打算释放或者丢弃,所以也就不需要释放内存。
FreeRTOS 的 动态内存可以申请的大小范围可以在 FreeRTOSConfig.h 文件中进行了定义:
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) ) //单位字节
这个宏其实是规定了操作系统的堆栈空间的总大小,动态申请的内存大小是不能操作这个这个值的。
我们可以通过函数 xPortGetFreeHeapSize 就能获得 FreeRTOS 动态内存的剩余情况,进而可以根据剩余情况优化 动态内存的大小。
heap_1 方式的动态内存管理有以下特点:
1)项目不需要删除任务、信号量、消息队列等已经创建的资源。
2)所申请的动态内存的时间是固定的,并且不会产生内存碎片。
3)是一种静态内存分配方案,因为申请的内存是不会被释放掉。
2、内存管理方式 2(heap_2.c)
heap_2 动态内存管理利用了自适应算法,并且支持内存释放, 但是不支持内存碎片整理。
FreeRTOS 的 动态内存可以申请的大小范围可以在 FreeRTOSConfig.h 文件中进行了定义:
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) ) //单位字节
通过函数 xPortGetFreeHeapSize 能获得 FreeRTOS 动态内存的剩余,可以根据剩余情况优化动态内存的大小。
heap_2 方 式的内存管理有以下特点:
1)在不考虑内存碎片的情况下,这种方式支持重复的任务、信号量、事件标志组、软件定时器等内部资源 的创建和删除。因为不使用的资源是支持释放的,所以可以让内存资源得到反复的使用!
2)如果申请和释放的动态内存大小是随机的,不建议采用这种动态内存管理方式。
3)项目中需要重复的创建和删除任务,如果每次创建需要动态内存大小相同,那么 heap_2 比 较适合,但每次创建需要动态内存大小不同,那么方式 heap_2 就不合适了,因为容易产生内存 碎片,内存碎片过多的话会导致无法申请出一个大的内存块出来。
4)项目中需要重复的创建和删除消息队列,也会出现类似上面的情况。
5)直接的调用函数 pvPortMalloc() 和 vPortFree() 也容易出现内存碎片。如果按一定顺序的申请和释放,基本没有内存碎片的,而不按顺序的随机申请和释放容易产生内存碎片。
6)如果随机的创建和删除任务、消息队列、事件标志组、信号量等内部资源也容易出现内存碎片。
3、 内存管理方式 3(heap_3.c)
这种方式实现的内存管理是对编译器提供的 malloc 和 free 函数进行了封装,保证是线程安全的。
FreeRTOS 的动态内存大小在 FreeRTOSConfig.h 文件中进行了定义:
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) ) //单位字节
heap_3 方式的内存管理有以下特点:
1)需要编译器提供 malloc 和 free 函数。
2)不具有时间确定性,即申请动态内存的时间不是固定的。
3)增加 RTOS 内核的代码量。
另外要特别注意一点,这种方式的动态内存申请和释放不是用的 FreeRTOSConfig.h 文件中定义的heap空间大小,而是用的编译器设置的heap空间大小。
4、内存管理方式 4(heap_4.c)
heap_4 动态内存管理利用了最适应算法,且支持内存碎片的回 收并将其整理为一个大的内存块。
FreeRTOS 的动态内存大小在 FreeRTOSConfig.h 文件中进行了定义:
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) ) //单位字节
heap_4 同时支持将动态内存设置在指定的 RAM 空间位置。
通过函数 xPortGetFreeHeapSize 就能获得 FreeRTOS 动态内存的剩余。
使用函数 xPortGetMinimumEverFreeHeapSize 能够获取从系统启 动到当前时刻的动态内存最小剩余。
heap_4 方式的 内存管理有以下特点:
1)可以用于需要重复的创建和删除任务、信号量、事件标志组、软件定时器等资源的项目中。
2)调用 pvPortMalloc() 和 vPortFree(),即使每次申请的内存大小都不同,也不会产 生很多的内存碎片。
3)申请动态内存的时间不是确定的。
5、 内存管理方式 5 (heap_5.c)
如果希望申请的空间可以采用不连续的内存区,比希望可以将内存定义在内部 SRAM 中的某一部分,或者外部 SRAM 的一部分,就可以采用 heap_5 动态内存管理 方式。
heap_5 内存管理通过函数 vPortDefineHeapRegions 进行初始化的,即在创建任 务 FreeRTOS 的内部资源前要优先调用这个函数 vPortDefineHeapRegions,否则是无法通过函数 pvPortMalloc 申请到动态内存的。
6、这五种内存申请方式的比较
有关五种动态内存管理方式简单总结如下:
1)heap_1.c:五种方式里面最简单的,但是申请的内存不允许释放。
2)heap_2.c:支持动态内存的申请和释放,但是不支持内存碎片的处理,无法将碎片内存合并成一个大的内存块。
3)heap_3.c:将编译器自带的 malloc 和 free 函数进行简单的封装,以支持线程安全,即支持多任务调 用。
4)heap_4.c:支持动态内存的申请和释放,支持内存碎片处理,支持将动态内存设置在个固定的地址(内部或者外部 RAM)。
5)heap_5.c:在 heap_4.c 的基础上支持将动态内存设置在不连续的区域上。
其实大多数项目中使用的都是 heap_4.c 这种内存的管理方式,这种方式支持动态内存的申请和释放,支持内存碎片处理,还支持将动态内存设置在个固定的地址,对大多数的项目都有很高的满足性,基本上都能够适配上了!
五种方式不分优劣吧,看自己的项目的需求,合适才是最好的!!!
全部0条评论
快来发表一下你的评论吧 !