FreeRTOS学习:内存管理

news/2024/9/24 10:18:30/

FreeRTOS内存管理简介

在使用 FreeRTOS 创建任务、队列、信号量等对象的时候, FreeRTOS 一般都提供了两种方法,

  • 动态方法创建:自动地从 FreeRTOS 管理的内存堆中申请所创建对象所需的内存,在对象被删除后,又可以将这块内存释放会 FreeRTOS 管理的内存堆。
     
  • 静态方法创建:需要用户提供各种内存空间,并且使用静态方式占用的内存空间一般固定下来了,即使任务、队列等被删除后,这些被占用的内存空间也没有其他用途。

备注 :动态方式管理比静态方式更加灵活。

        标准的 C 库也提供了函数 malloc()和函数 free()来实现动态地申请和释放内存,但是标准 C 库的动态内存管理方法有如下几个缺点,

  • 占用大量的代码空间,不适合用在资源紧缺的嵌入式系统
  • 没有线程安全的相关机制。
  • 具有不确定性,体现在每次执行的时间不同。
  • 内存碎片化
     

FreeRTOS内存管理算法 

 FreeRTOS提供了5种动态内存管理算法,分别为heap_1、heap_2、heap_3、heap_4和heap_5,这 5 种动态内存管理算法各自的特点如下所示:

  • heap_1: 最简单,只允许申请内存,不允许释放内存。
  • heap_2: 允许申请和释放内存,但不能合并相邻的空闲内存块。
  • heap_3: 简单封装 C 库的函数 malloc()和函数 free(), 以确保线程安全。
  • heap_4: 允许申请和释放内存,并且能够合并相邻的空闲内存块,减少内存碎片的产生。
  • heap_5: 能够管理多个非连续内存区域的 heap_4。

 heap_1内存管理算法

heap_1只实现了pvPortMalloc,没有实现vPortFree,只能申请内存,无法释放。

如果工程创建好的任务、队列、信号量等都不需要被删除,可以使用heap_1。

heap_1 内存管理算法管理的内存堆是一个数组,在申请内存的时候, heap_1 内存管理算法只是简单地从数组中分出合适大小的内存。

heap_1内存管理算法分配过程如下,

可以看到heap_1内存管理算法就像切蛋糕,切掉了就没有了。

heap_2内存管理算法

  • 相比于 heap_1 内存管理算法, heap_2 内存管理算法使用了最适应算法,以支持释放先前申请的内存。
  • heap_2 内存管理算法并不能将相邻的空闲内存块合并成一个大的空闲内存块,因此 heap_2 内存管理算法不可避免地会产生内存碎片。

最适应算法:就是将空闲内存按照内存块大小排序,当你申请一个内存时,找到最小的,可以满足所申请的内存大小的的内存块,并将这个内存块分配出去,分配出去的内存块剩余大小任然是空闲状态。

内存碎片:内存碎片是由于多次申请和释放内存,但释放的内存无法与相邻的空闲内存合并而产生的。

heap_2内存管理算法分配过程如下,

heap_2适用于频繁的创建和删除任务,且所创建的任务堆栈都相同的场景。

heap_3内存管理算法

heap_3内存管理算法就是封装了C库的malloc和free函数,建议自行学习

heap_4内存管理算法

heap_4 内存管理算法使用了首次适应算法,也支持内存的申请与释放,并且 heap_4 内存管理算法还能够将空闲且相邻的内存进行合并,从而减少内存碎片的现象。

首次适用算法:就是将空闲内存块按照地址由高到低进行排序,当你要申请一块内存时,先是根据地址由高到低找到可以满足所需内存的内存块,然后也是一样,内存块多余的内存仍然是空闲状态。

heap_4内存管理算法分配过程如下,

heap_4适用于频繁的分配,释放不同大小的内存的场景。

heap_5内存管理算法

heap_5 内存管理算法是在 heap_4 内存管理算法的基础上实现的,因为 heap_5 内存管理算法使用与 heap_4 内存管理算法相同的内存分配、释放和合并算法,但是 heap_5 内存管理算法在 heap_4 内存管理算法的基础上实现了管理多个非连续内存区域的能力。
 

heap_5内存管理算法默认并没有定义内存堆 ,需要用户手动调用函数进行分配,heap_5 内存管理算法定义了一个结构体,用于表示内存区域的信息

typedef struct HeapRegion
{uint8_t * pucStartAddress; /* 内存区域的起始地址 */size_t xSizeInBytes; /* 内存区域的大小,单位:字节 */
} HeapRegion_t;

当我们要指定多块不连续的内存时,可以向如下一样指定,

const HeapRegion_t xHeapRegions[] =
{{(uint8_t *)0x80000000, 0x10000}, /* 内存区域 1 */{(uint8_t *)0x90000000, 0xA0000}, /* 内存区域 2 */{NULL, 0} /* 数组终止标志 */
};
vPortDefineHeapRegions(xHeapRegions);

heap_5适用于嵌入式系统中内存地址不连续的场景下使用。

内存管理函数

由于内存管理函数比较简单,下面介绍三个有关FreeRTOS内存管理的函数,

void* pvPortMalloc(size_t xWantedSize)

xWantedSize:申请的内存大小,以字节为单位

返回值:返回一个指针,指向以分配大小的内存,申请失败则返回NULL

void vPortFree(void* pv)

*pv:指针指向一个要释放的内存 

size_t xPortGetFreeHeapSize(void)

返回值:返回当前剩余的空闲内存大小

备注:在一段内存没有被释放之前绝对不能在调用依次函数pvPortMalloc()为其再次分配内存,否则会导致内存泄漏。


http://www.ppmy.cn/news/1514461.html

相关文章

react 的学习随记

npx create-react-app my-app 创建一个名叫my-app的react的项目 npm run eject 运行 显示config 文件夹 react jsx (使用时将babel 将jsx转为js) 单页面时需要引用 1,样式(在虚拟dom时) 1. 引用样式时 用classNa…

优化代码设计:构建高效、安全与可维护的应用程序

引言 在软件开发中,良好的编码习惯和架构设计对于提高代码质量和维护性至关重要。本文将探讨几种实用的方法和技术,帮助开发者创建更高效、更安全且易于维护的应用程序。 一、封装常用代码为工具类 代码重用是软件工程中的基本原则之一。通过将频繁使用…

服务器在插入一个新的磁盘后需要做的操作(仅限新盘)

进入服务器的raid配置界面(重启,按CtrlR进入PERC RAID配置工具) 在RAID配置界面中,进行插入操作,出现新的磁盘后,光标移到菜单栏,按F2进入设置界面,选择最下面的【Convert to Non-R…

微服务设计原则——高性能:存储设计

文章目录 1.读写分离2.分库分表3.动静分离4.冷热分离5.重写轻读6.数据异构参考文献 任何一个系统,从单机到分布式,从前端到后台,功能和逻辑各不相同,但干的只有两件事:读和写。而每个系统的业务特性可能都不一样&#…

【吊打面试官系列-Memcached面试题】memcached 是如何做身份验证的?

大家好,我是锋哥。今天分享关于 【memcached 是如何做身份验证的? 】面试题,希望对大家有帮助; memcached 是如何做身份验证的? 没有身份认证机制!memcached 是运行在应用下层的软件(身份验证应…

后端开发刷题 | 有效括号序列【栈】

描述 给出一个仅包含字符(,),{,},[和],的字符串,判断给出的字符串是否是合法的括号序列 括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。 数据范围&#xff1…

【数据结构】汇总八、排序算法

排序Sort 【注意】本章是 排序 的知识点汇总,全文1万多字,含有大量代码和图片,建议点赞收藏(doge.png)!! 【注意】在这一章,记录就是数据的意思。 排序可视化网站: D…

3D 打印的突破:热引发剂在立体光刻中的应用

在当今科技飞速发展的时代,3D打印技术作为一项具有创新性和颠覆性的技术,正不断改变着我们的生产和生活方式。今天,向大家介绍的是一项关于3D打印的重要研究成果《3D printing by stereolithography using thermal initiators》发表于《Natur…