简介

Freertos的内存管理分别在heap_1.c,heap_2.c,heap_3.c,heap_4.c,heap_5.c个文件中,选择合适的一种应用于嵌入式项目中即可。

本文的图片中
红色部分Block代表:在内存对齐过程中舍弃掉的部分字节。
蓝色部分Block代表:链表结构体头,包含可以分配的内存大小和Next指针。
绿色部分Block代表:实际可分配给用户的内存。
黄色部分Block代表:已经分配给用户的内存。


heap_1.c

特点:

  1. 最简单的内存分配算法。
  2. 分配后无法释放内存。
  3. 支持1/2/4/8/16/32多种内存对齐方式。
  4. 线程安全。

初始化

  • ucHeadp数组代表整个堆内存空间。
  • xNextFreeByte = 0。
  • 初始化以后pucAlignedHeap指针会指向内存对齐后的第一个位置。

*pvPortMalloc():

  • 依次返回pvReturn(pucAlignedHeap+xNextFreeByte)所指向的地址,并更新xNextFreeByte大小。


### vPortFree():

  • 无法使用,传入的指针非空会进入断言。

heap_2.c

特点:

  1. 采用链表结构管理,按内存块大小排序。
  2. 分配后可以释放内存,但是会产生内存碎片。
  3. 支持1/2/4/8/16/32多种内存对齐方式。
  4. 线程安全。

初始化

  • ucHeap数组代表整个堆内存空间。
  • 初始化以后pucAlignedHeap指针会指向内存对齐后的第一个位置。
  • xStart表示链表头,pxFirstFreeBlock代表第一块可分配空间,xEnd代表链表尾。

*pvPortMalloc():

  • 按内存字节对齐方式调整实际分配大小。(实际大小=内存对齐+链表结点结构体大小)
  • 遍历整个内存链表,如果找到足够分配的内存Block头,则加上结构体头偏移量,将pvReturn位置记录待返回给用户,并将该结点从链表中移除。
  • 分配完成后,如果剩余的内存大小仍然大于最小的BlockSize(包含链表结构体),就将该Block切割,并按照BlockSize从小到大的方式插入空闲内存链表。


###vPortFree():

  • Free的过程非常简单,只是根据传入的指针参数,反向找到结构体头,然后根据该节点BlockSize从小到大重新插入空闲内存链表中即可。

总结:

  1. 内存的分配和释放过程是线程安全的。
  2. 在内存分配和释放过程会产生内存碎片,所以heap_2.c不适用于频繁地内存分配的场合。试想这样一种情况:不停地进行小片内存分配(比如:8个字节)直到内存用完,分配完成后全部重新Free,由于结点信息仍然存在,将导致以后都无法分配超过8个字节的内存。

heap_3.c

特点:

  1. 使用标准库中的malloc和free方法。
  2. 无法在中断中分配和释放内存。
  3. 线程安全。

在标准库的基础上,简单地加上线程安全的处理,保证malloc不会被线程切换打断。


heap_4.c

特点:

  1. 采用链表结构管理,按地址大小排序。
  2. 分配后可以释放内存,不会产生内存碎片。
  3. 支持1/2/4/8/16/32多种内存对齐方式。
  4. 线程安全。

初始化

  • ucHeadp数组代表整个堆内存空间。
  • 初始化以后pucAlignedHeap指针会指向内存对齐后的第一个位置。
  • xStart表示链表头,pxFirstFreeBlock代表第一块可分配空间,xEnd代表链表尾。和heap_2.c不一致的是这里的链尾结构体也分配在ucHeap内存中。

*pvPortMalloc():

  • 按内存字节对齐方式调整实际分配大小。(实际大小=内存对齐+链表结点结构体大小)
  • 遍历整个内存链表,如果找到足够分配的内存Block头,则加上结构体头偏移量,将pvReturn位置记录待返回给用户,并将该结点从链表中移除。
  • 如果剩余的内存大小仍然大于最小的BlockSize(包含链表结构体),就将Block切割,并按照地址从小到大的方式插入内存链表,并更新xFreeBytesRemaining。


###vPortFree():

  • 根据传入的指针参数,反向找到结构体头,然后迭代空闲链表,根据该节点的地址从低到高,找到相应的插入位置。
  • 当Free的时候,有两种情况,一种是连续(如图中黄色块3),一种是不连续(如图中黄色块1,2)。
  • 插入空闲内存链表后,如果该节点与后面的节点是连续的,则将这两个节点整合成一个大的节点。

总结:

  1. 内存的分配和释放过程是线程安全的。
  2. 和heap_2.c非常相似,最大不同点在于释放内存的时候不会产生碎片,具体做法是在插入空闲内存链表的时候多了一步操作:如果两个空闲节点在内存上是连续的,则将这两个节点重新整合成一个。
  3. 
另外一点和heap_2.c不同的地方在于,空闲内存链表排序方式不一样,heap_2.c是按照blockSize排序,而heap_4.c是按照内存地址排序,所以heap_4.c的空闲链表在内存上是很容易整合的,而heap_2.c由于没有按内存地址排序,所以整合比较麻烦。

heap_5.c

特点:

  1. 采用链表结构管理,按地址大小排序。
  2. 分配后可以释放内存,不会产生内存碎片。
  3. 支持1/2/4/8/16/32多种内存对齐方式。
  4. 线程安全。
  5. 可以自定义内存区。

Malloc和Free方法和heap_4.c一模一样。
区别在与heap_4.c使用prvHeapInit()函数将ucHeap这个全局变量作为内存区,而heap_5.c没有这个prvHeapInit()函数,而是提供了另一个函数vPortDefineHeapRegions(),自己定义内存区。

FreeRTOS内存管理的更多相关文章

  1. FreeRTOS——内存管理

    1. 标准malloc() 和 free() 库函数的缺陷: 1)在小型的嵌入式系统中,可能不可用. 2)具体实现相对较大,占用较多宝贵的代码空间. 3)通常不具备线程安全性. 4)具有不确定性,每次 ...

  2. FreeRTOS的内存管理

    FreeRTOS提供了几个内存堆管理方案,有复杂的也有简单的.其中最简单的管理策略也能满足很多应用的要求,比如对安全要求高的应用,这些应用根本不允许动态内存分配的. FreeRTOS也允许你自己实现内 ...

  3. FreeRTOS --(2)内存管理 heap1

    转载自https://blog.csdn.net/zhoutaopower/article/details/106631237 FreeRTOS 提供了5种内存堆管理方案,分别对应heap1/heap ...

  4. 轻量级操作系统FreeRTOS的内存管理机制(一)

    本文由嵌入式企鹅圈原创团队成员朱衡德(Hunter_Zhu)供稿. 近几年来,FreeRTOS在嵌入式操作系统排行榜中一直位居前列,作为开源的嵌入式操作系统之一,它支持许多不同架构的处理器以及多种编译 ...

  5. FreeRTOS 动态内存管理

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 FreeRTOS 动态内存管理,动态内存管理是 FreeRTOS 非常重要的一项功能,前面 ...

  6. FreeRTOS --(6)内存管理 heap5

    转载自https://blog.csdn.net/zhoutaopower/article/details/106748308 FreeRTOS 中的 heap 5 内存管理,相对于 heap 4&l ...

  7. FreeRTOS --(5)内存管理 heap4

    FreeRTOS 中的 heap 4 内存管理,可以算是 heap 2 的增强版本,在 <FreeRTOS --(3)内存管理 heap2>中,我们可以看到,每次内存分配后都会产生一个内存 ...

  8. FreeRTOS --(3)内存管理 heap2

    在<FreeRTOS --(2)内存管理 heap1>知道 heap 1 的内存管理其实只是简单的实现了内存对齐的分配策略,heap 2 的实现策略相比 heap 1 稍微复杂一点,不仅仅 ...

  9. freertos之内存管理

    任务.信号量.邮箱才调度器开始调度之前就应该创建,所以它不可能像裸奔程序那样的函数调用能确定需要多少内存资源,RTOS提供了3种内存管理的方法: 1 方法一:确定性好适合于任务.信号量.队列都不被删除 ...

随机推荐

  1. java笔记--重定向输出流实现程序输出到日志

    重定向输出流实现程序输出到日志 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877248.html "谢谢-- 利用Sy ...

  2. kettle 合并记录

    转自: http://blog.itpub.net/post/37422/464323 看到别人的脚本用到 合并记录 步骤,学下下. 该步骤用于将两个不同来源的数据合并,这两个来源的数据分别为旧数据和 ...

  3. Python学习---基于JQuery的Ajax实现[快捷+底层$.ajax]

    快捷API <1>$.get(url, [data], [callback], [type]) <2>$.post(url, [data], [callback], [type ...

  4. ISA 连接非443端口的https站点提示错误

    ISA 连接非443端口的https站点提示错误:12204 The specified Secure Sockets Layer (SSL) port is not allowed. ISA Ser ...

  5. August 21st 2017 Week 34th Monday

    In fact, the happiest fairy tale is no more than the simple days we have together. 其实全世界最幸福的童话,也比不上我 ...

  6. Python 处理脚本的命令行参数(三):使用argparse

    # coding:utf-8 # 测试argparse模块的基本用法 import argparse # 创建参数解析对象,并添加脚本用法帮助 parser = argparse.ArgumentPa ...

  7. 019.2 map集合类

    Map<k,v>Map:双列集合,一次存一对,键值对,类似于python的字典.共性功能:1.添加    v put(key,value)     //返回key的旧值    putAll ...

  8. js实现点击按钮显示某个区域 然后点击页面中任意其他位置,隐藏该区域

    $(".licat-header-list").on("click",function(e){ $(this).addClass("active&qu ...

  9. Window窗口布局 --- DecorView浅析

    开发中,通常都是在onCreate()中调用setContentView(R.layout.custom_layout)来实现想要的页面布局,我们知道,页面都是依附在窗口之上的,而DecorView即 ...

  10. 【MySQL-123】MySQL8.0.12 安装于Win10

    参考blog:MySQL8.0.12 安装及配置 [坑一]输入net start mysql时,MYSQL服务无法启动. 问题:第三步my.ini文件编码错误. 解决方案:https://blog.c ...