FreeRTOS 内存管理方案

摘自:《Free RTOS 内核实现与应用开发实战—基于STM32》

FreeRTOS 内存管理模块管理用于系统中的内存资源,它是操作系统的核心模块之一。主要包括内存的初始化、分配以及释放。

在嵌入式实时操作系统中,调用malloc()和free()是有风险的,原因有以下几点:

①这些函数在小型嵌入式系统中并不总是可用的,小型嵌入式设备中的RAM不足。

②它们的实现可能非常的大,占据了相当大的一块代码空间。

③它们几乎都不是安全的。

④它们并不是确定的,每次调用这些函数执行的时间可能都不一样。

⑤它们有可能产生碎片。

⑥这两个函数会是的链接器配置的复杂。

⑦如果允许堆空间的生长方向覆盖其他变量占据的内存,它们会成为debug的灾难。

Free RTOS对内存管理做了很多事情,v9.0.0版本提供了5种内存管理算法,分别是heap_1.c、heap_2.c、heap_3.c、heap_4.c、heap_5.c,在使用时选择其中一个添加到我们的工程中去即可。

1.heap_1.c

    heap_1.c管理方案是Free RTOS提供所有内存管理方案中最简单的一个,它只能申请内存而不能进行内存释放,并且申请内存的时间是一个常量,这样子对于要求安全的嵌入式设备来说是最好的,因为不允许内存释放,就不会产生内存碎片而导致系统崩溃,但是也有缺点,那就是内存利用率不高,某段内存只能用于内存申请的地方,即使该内存只使用一次,也无法让系统回收重新利用。

    实际上,大多数的嵌入式系统并不会经常动态申请与释放内存,一般都是在系统完成
的时候,就一直使用下去,永不删除, 所以这个内存管理方案实现简洁、安全可靠,使用
的非常广泛。

    heap1.c 方案具有以下特点:
    ①、 用于从不删除任务、队列、信号量、互斥量等的应用程序(实际上大多数使用
FreeRTOS 的应用程序都符合这个条件) 。
    ②、 函数的执行时间是确定的并且不会产生内存碎片。
 

2.heap_2.c

    heap_2.c方案与heap_1.c方案采用的内存管理算法不一样,它采用一种最佳匹配算法(best fit algorithm),比如我们申请100字节的内存,而可申请内存中有三块对应大小200字节,500字节和1000字节大小的内存块,按照算法的最佳匹配,这时候系统会把200字节的内存块进行分割并返回申请内存的起始地址,剩余的内存则插回链表留待下次申请。heap_2.c方案支持释放申请的内存,但是它不能把相邻的两个小的内存块合并成一个大的内存块,对于每次申请内存大小都比较固定的,这个方式是没有问题的,而对于每次申请并不是固定内存大小的则会造成内存碎片。

    heap2.c 方案具有以下特点:
    ①、 可以用在那些反复的删除任务、队列、信号量、等内核对象且不担心内存碎片的
应用程序。
    ②、 如果我们的应用程序中的队列、任务、信号量、 等工作在一个不可预料的顺序,
这样子也有可能会导致内存碎片。
    ③、 具有不确定性,但是效率比标准 C 库中的 malloc 函数高得多
    ④、 不能用于那些内存分配和释放是随机大小的应用程序。

3.heap_3.c

     heap_3.c 方案只是简单的封装了标准 C 库中的 malloc()和 free()函数, 并且能满足常用
的编译器。 重新封装后的 malloc()和 free()函数具有保护功能,采用的封装方式是操作内存
前挂起调度器、完成后再恢复调度器。
     heap_3.c 方案具有以下特点:
    ①、 需要链接器设置一个堆, malloc()和 free()函数由编译器提供。
    ②、 具有不确定性。
    ③、 很可能增大 RTOS 内核的代码大小。

4.heap_4.c

     heap_4.c 方案与 heap_2.c 方案一样都采用最佳匹配算法来实现动态的内存分配,但是
不一样的是 heap_4.c 方案还包含了一种合并算法,能把相邻的空闲的内存块合并成一个更
大的块,这样可以减少内存碎片。 heap_4.c 方案特别适用于移植层中可以直接使用
pvPortMalloc()和 vPortFree()函数来分配和释放内存的代码。

     内 存 分 配 时 需 要 的 总 的 堆 空 间 由 文 件 FreeRTOSConfig.h 中 的 宏
configTOTAL_HEAP_SIZE 配置,单位为字。 通过调用函数 xPortGetFreeHeapSize() 我们可
以知道还剩下多少内存没有使用, 但是并不包括内存碎片。 这样一来我们可以实时的调整
和优化 configTOTAL_HEAP_SIZE 的大小。

     heap_4.c 方案的空闲内存块也是以单链表的形式连接起来的, BlockLink_t 类型的局部
静态变量 xStart 表示链表头,但 heap_4.c 内存管理方案的链表尾部则保存在内存堆空间最
后位置,并使用 BlockLink_t 指针类型局部静态变量 pxEnd 指向这个区域(而 heap_2.c 内
存管理方案则使用 BlockLink_t 类型的静态变量 xEnd 表示链表尾)
     heap_4.c 内存管理方案的空闲块链表不是以内存块大小进行排序的,而是以内存块起
始地址大小排序, 内存地址小的在前,地址大的在后,因为 heap_4.c 方案还有一个内存合
并算法, 在释放内存的时候,假如相邻的两个空闲内存块在地址上是连续的,那么就可以
合并为一个内存块, 这也是为了适应合并算法而作的改变。

     heap_4.c 方案具有以下特点:
    ①、可用于重复删除任务、队列、信号量、互斥量等的应用程序
    ②、可用于分配和释放随机字节内存的应用程序, 但并不像 heap2.c 那样产生严重的内
存碎片。
    ③、具有不确定性,但是效率比标准 C 库中的 malloc 函数高得多。

5.heap_5.c

     heap_5.c 方案在实现动态内存分配时与 heap4.c 方案一样, 采用最佳匹配算法和合并算
法,并且允许内存堆跨越多个非连续的内存区,也就是允许在不连续的内存堆中实现内存
分配,比如用户在片内 RAM 中定义一个内存堆,还可以在外部 SDRAM 再定义一个或多
个内存堆,这些内存都归系统管理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值