简介

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. 【Oracle】Update方法

    1.单表更新 update customers set city_name='山西省太原市' where city_name='山西太原' 2.两表(多表)关联update -- 被修改值由另一个表运 ...

  2. Sql Server关于日期查询时,如果表中日期到具体某个时间

    1.如果查询日期参数为'2017/02/21',而数据库表中的字段为'2017/02/21 12:34:16.963',则需要格式化一下日期才能查询出来,如下 select * from table ...

  3. Windows as a Service(1)—— Windows 10服务分支

    前言 作为公司的IT管理员,管理全公司Windows 10操作系统的更新一直是工作中的头疼之处.微软提供了很多方法来帮助我们管理公司的Windows 10更新,比如Windows Server Upd ...

  4. ZT I Believe I Can Fly(我相信我能飞)

    I Believe I Can Fly(我相信我能飞) 歌手:R. Kelly(罗 凯利) 歌词部分 I used to think that I could not go on 我原以为我无法坚持下 ...

  5. [BZOJ 2186][SDOI 2008] 莎拉公主的困惑

    2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 4519  Solved: 1560[Submit][S ...

  6. Angular不同版本对应的Bootstrap组件

    AngularJS 1.x版本对应的 bootstrap组件库是ui-bootstrap; http://www.cnblogs.com/pilixiami/p/5597634.html Angula ...

  7. Redis命令、数据结构场景、配置文件总结

    本文大纲 一.常用数据类型简介二.redis操作命令三.redis配置文件详解四.redis数据类型使用场景 一.常用数据类型简介 redis常用五种数据类型:string,hash,list,set ...

  8. 【php】php与mysql初体验

    第一次体验在web站点上使用MySQL数据库,遇到了很多问题,总结如下: 1.安装XAMPP软件后,将文件放到hotdocs文件夹下,要访问其中的文件,使用localhost/XXX/XXX ,路径要 ...

  9. WiFi密码忘记了怎么办之解决方案

    随着科技不断进步,网络产品也越来越便宜了.家家户户基本上都有能力装上宽带. 但是有的时候,时间久了,我们可能会忘记密码(密码设置比较复杂的情况下).那么如何找到密码呢? 通常的办法有很多,百度或者Go ...

  10. urlparse 用法

    ifrom urllib2 import urlparse ‘’ captcha_id = urlparse.parse_qs(urlparse.urlparse(link).query, True) ...