FreeRTOS 内存管理策略

news2025/1/31 20:06:42

目录

1. FreeRTOS 的核心功能

2. 为什么 FreeRTOS 要自己实现内存管理

3. FreeRTOS 的5种内存管理策略

3.1 Heap_1(只建不删)

3.2 Heap_2(Heap1_Pro、提供删除,产生碎片)

内存碎片是怎么出现的

3.3 Heap_3(传统malloc - free)

3.4 Heap_4(Heap2_Pro,解决碎片)

3.5 Heap_5(Heap4_Pro,可管理分隔内存)



1. FreeRTOS 的核心功能

2. 为什么 FreeRTOS 要自己实现内存管理

        后续的章节涉及这些内核对象: task、 queue、 semaphores 和 event group 等。为了
让 FreeRTOS 更容易使用,这些内核对象一般都是动态分配:用到时分配,不使用时释放。

使用内存的动态管理功能,简化了程序设计:不再需要小心翼翼地提前规划各类对象,简
化 API 函数的涉及,甚至可以减少内存的使用。

        内存的动态管理是 C 程序的知识范畴,并不属于 FreeRTOS 的知识范畴,但是它跟
FreeRTOS 关系是如此紧密,所以我们先讲解它。

        在 C 语言的库函数中,有 mallc、 free 等函数,但是在 FreeRTOS 中,它们不适用:

  • 不适合用在资源紧缺的嵌入式系统中
  • 这些函数的实现过于复杂、占据的代码空间太大(还是因为资源紧缺)
  • 并非线程安全的(thread-safe)
  • 运行有不确定性:每次调用这些函数时花费的时间可能都不相同
  • 内存碎片化(浪费内存)
  • 使用不同的编译器时,需要进行复杂的配置

注意:我们经常"堆栈"混合着说,其实它们不是同一个东西:

堆: heap,就是一块空闲的内存,需要提供管理函数

  • malloc:从堆里划出一块空间给程序使用
  • free:用完后,再把它标记为"空闲"的,可以再次使用

栈: stack,函数调用时局部变量保存在栈中,当前程序的环境也是保存在栈中

  • 可以从堆中分配一块空间用作栈

3. FreeRTOS 的5种内存管理策略

3.1 Heap_1(只建不删)

适用场景:创建的任务、队列、信号量等不需要删除。

        它只实现了 pvPortMalloc,没有实现 vPortFree。如果你的程序不需要删除内核对象,那么可以使用 heap_1:

  • 实现最简单
  • 没有碎片问题(Good)
  • 一些要求非常严格的系统里,不允许使用动态内存,就可以使用 heap_1

它的实现原理很简单,首先定义一个大数组:

然后,对于 pvPortMalloc 调用时,从这个数组中分配空间。

FreeRTOS 在创建任务时,需要 2 个内核对象: task control block(TCB)、 stack。
使用 heap_1 时,内存分配过程如下图所示:

  • A:创建任务之前整个数组都是空闲的
  • B:创建第 1 个任务之后,蓝色区域被分配出去了
  • C:创建 3 个任务之后的数组使用情况

3.2 Heap_2(Heap1_Pro、提供删除,产生碎片)

适用场景:频繁的创建和删除任务,且所创建的任务堆栈都相同此时不会出现碎片化的问题

        Heap_2 之所以还保留,只是为了兼容以前的代码。新设计中不再推荐使用 Heap_2。
建议使用 Heap_4 来替代 Heap_2,更加高效。

Heap_2 也是在数组上分配内存,跟 Heap_1 不一样的地方在于:

  • Heap_2 使用最佳匹配算法(best fit)来分配内存
  • 它支持 vPortFree

最佳匹配算法:

  • 假设 heap 有 3 块空闲内存: 5 字节、 25 字节、 100 字节
  • pvPortMalloc 想申请 20 字节
  • 找出最小的、能满足 pvPortMalloc 的内存: 25 字节
  • 把它划分为 20 字节、 5 字节
  • 返回这 20 字节的地址
  • 剩下的 5 字节仍然是空闲状态,留给后续的 pvPortMalloc 使用

        与 Heap_4 相比, Heap_2 不会合并相邻的空闲内存,所以 Heap_2 会导致严重的"碎片
化"问题。

        但是,如果申请、分配内存时大小总是相同的,这类场景下 Heap_2 没有碎片化的问
题。所以它适合这种场景:频繁地创建、删除任务,但是任务的栈大小都是相同的(创建任
务时,需要分配 TCB 和栈, TCB 总是一样的)。

虽然不再推荐使用 heap_2,但是它的效率还是远高于 malloc、 free。

使用 heap_2 时,内存分配过程如下图所示:

  • A:创建了 3 个任务
  • B:删除了一个任务,空闲内存有 3 部分:顶层的、被删除任务的 TCB 空间、被删除任务的 Stack 空间
  • C:创建了一个新任务,因为 TCB、栈大小跟前面被删除任务的 TCB、栈大小一致,所以刚好分配到原来的内存

内存碎片是怎么出现的

3.3 Heap_3(传统malloc - free)

        Heap_3 使用标准 C 库里的 malloc、 free 函数,所以堆大小由链接器的配置决定,配
置项 configTOTAL_HEAP_SIZE 不再起作用。直接用C库的 malloc - free

        C 库里的 malloc、 free 函数并非线程安全的Heap_3 中先暂停 FreeRTOS 的调度器
再去调用这些函数,使用这种方法实现了线程安全。(用 malloc 和 free 的效率不高),因为heap1和2是在数组中分配内存操作,数组操作比较快和效率高。

        缺点:malloc-free存在碎片问题,一样也存在分配失败的风险。

3.4 Heap_4(Heap2_Pro,解决碎片)

        跟 Heap_1、 Heap_2 一样, Heap_4 也是使用大数组来分配内存。

        Heap_4 使用首次适应算法(first fit)来分配内存。它还会把相邻的空闲内存合并为一个
更大的空闲内存,这有助于较少内存的碎片问题。
(heap2的升级版)

首次适应算法:

  • 假设堆中有 3 块空闲内存: 5 字节、 200 字节、 100 字节
  • pvPortMalloc 想申请 20 字节
  • 找出第 1 个能满足 pvPortMalloc 的内存: 200 字节
  • 把它划分为 20 字节、 180 字节
  • 返回这 20 字节的地址
  • 剩下的 180 字节仍然是空闲状态,留给后续的 pvPortMalloc 使用

        Heap_4 会把相邻空闲内存合并为一个大的空闲内存,可以减少内存的碎片化问题
用于这种场景:频繁地分配、释放不同大小的内存。

Heap_4 的使用过程举例如下:

  • A:创建了 3 个任务
  • B:删除了一个任务,空闲内存有 2 部分:顶层的、被删除任务的 TCB 空间、被删除任务的 Stack 空间合并起来的
  • C:分配了一个 Queue,从第 1 个空闲块中分配空间
  • D:分配了一个 User 数据,从 Queue 之后的空闲块中分配
  • E:释放的 Queue, User 前后都有一块空闲内存
  • F:释放了 User 数据, User 前后的内存、 User 本身占据的内存, 合并为一个大的空闲内存

Heap_4 执行的时间是不确定的,但是它的效率高于标准库的 malloc、 free。

3.5 Heap_5(Heap4_Pro,可管理分隔内存)

Heap_5 分配内存、释放内存的算法跟 Heap_4 是一样的。

相比于 Heap_4, Heap_5 并不局限于管理一个大数组:它可以管理多块、分隔开的内存

在嵌入式系统中,内存的地址可能并不连续,这种场景下可以使用 Heap_5。

既然内存时分隔开的,那么就需要进行初始化:确定这些内存块在哪、多大:

  • 在使用 pvPortMalloc 之前,必须先指定内存块的信息
  • 使用 vPortDefineHeapRegions 来指定这些信息

怎么指定一块内存?使用如下结构体:



怎么指定多块内存?使用一个 HeapRegion_t 数组,在这个数组中,低地址在前、高地址在后。

vPortDefineHeapRegions 函数原型如下:

把 xHeapRegions 数组传给 vPortDefineHeapRegions 函数,即可初始化 Heap_5。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1000043.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Stream流操作

一、流的分类 1.1 流的方向:输入流和输出流 输入流: 输入到计算机内存,键盘键入,文件读取等 输出流: 从计算机内存输出,写入显示器,文件写入等 1.2 流的功能:节点流和过滤流 节点流…

前端excel写入信息并下载

// 需要npm install xlsx,安装xlsx依赖 const data {management: {zh-cn: 管理,en-us: ,}, };function dataToFormat(data) {let newdata [];for (let i in data) {newdata.push({序号: i,,内容: data[i][zh-cn],});}return newdata; }function exportToExcel(old…

京东全品类指数查询API接口

京东全品类指数查询API接口(Jingdong full category index query API interface)是在京东平台的数据支撑基础上开发出来的一种应用程序编程接口,是由京东手机数码指数接口、食品饮料指数接口、母婴保健指数接口、服装鞋包指数接口、办公设备指…

开发者的商业智慧:产品立项策划你知道多少?

文章目录 想法的萌芽🌟初步评估产品可行性🍊分析核心功能和特点以及竞争对手📝大健康监测📝时尚新科技产品📝准确性📝多功能📝品牌口碑📝数据分析与个性化建议📝社交互动…

vue中预览xml并高亮显示

项目中有需要将接口返回的数据流显示出来&#xff0c;并高亮显示&#xff1b; 1.后端接口返回blob,类型为xml,如图 2.页面中使用pre code标签&#xff1a; <pre v-if"showXML"><code class"language-xml">{{xml}}</code></pre> …

电阻和电容

目录 1、常见的电阻器 2、电容 ​编辑 1、常见的电阻器 对于电阻需要了解三个参数&#xff08;查询电阻的数据手册&#xff09;&#xff1a; 1、封装&#xff1a;就是电阻的尺寸或者大小&#xff0c;看焊在你的pcb板上是否合适。 2、标称&#xff1a;电阻的电阻大小、精度、…

学习笔记-静态路由配置有来无回导致无法访问目标IP

配置拓扑图&#xff1a; 已经在R1、R2、R3相应端口配置了相应IP。 在R2上配置静态路由&#xff1a; [R2]ip route-static 10.0.3.0 24 10.0.23.3 [R2]ip route-static 10.0.13.0 24 10.0.23.3执行tracert 10.0.3.3&#xff0c;可以到达目标IP 执行tracert 10.0.13.3&#xff…

夯实网络安全基石,筑牢网络安全防线

没有网络安全就没有国家安全&#xff0c;这句话我们常常能在各种新闻里看见。安全是发展的前提&#xff0c;发展是安全的保障&#xff0c;共同推进安全和发展。Z强调&#xff1a;“要坚持依法治网、依法办网、依法上网。”今年的国家网络安全宣传周在9月11日至17日全国范围内开…

win11右键任务栏没有任务管理器怎么办

大多数情况下&#xff0c;我们可以直接右击任务栏选择任务管理器打开&#xff0c;但是有小伙伴反映win11中右击任务栏没有任务管理器&#xff0c;遇到这种问题该怎么解决呢&#xff0c;这里小编就给大家详细介绍一下win11右击 任务栏没有任务管理器的解决方法&#xff0c;有需要…

HuTool 使用教程

HuTool 官网 Hutool — &#x1f36c;A set of tools that keep Java sweet. 一、简介 准备环境 Hutool是一个小而全的Java工具类库&#xff0c;通过静态方法封装&#xff0c;降低相关API的学习成本&#xff0c;提高工作效率&#xff0c;使Java拥有函数式语言般的优雅&#xff…

SQL 注入漏洞攻击

文章目录 1. 介绍2. 无密码登录3. 无用户名无密码登录4. 合并表获取用户名密码 1. 介绍 假设你用自己的用户名和密码登录了一个付费网站&#xff0c;网站服务器就会查询一下你是不是 VIP 用户&#xff0c;而用户数据都是放在数据库中的&#xff0c;服务器通常都会向数据库进行查…

NLP信息抽取全解析:从命名实体到事件的PyTorch实战指南

目录 引言背景和信息抽取的重要性文章的目标和结构 信息抽取概述什么是信息抽取信息抽取的应用场景信息抽取的主要挑战 实体识别什么是实体识别实体识别的应用场景PyTorch实现代码输入、输出与处理过程 关系抽取什么是关系抽取关系抽取的应用场景PyTorch实现代码输入、输出与处…

松下DC-GH6 MOV音频使用可变长且存在00的特殊案例分析

松下mov常见的是GH系列机型&#xff0c;其音频格式一般采用SOWT其实是PCM&#xff0c;只不过一般是一个声道TRAK&#xff08;左右两个声道合成到一个TRAK中&#xff09;。此次遇到的DC-GH6却是一个4声道独立TRAK的松下MOV文件&#xff0c;这种的倒是在索尼上也有遇到过&#xf…

Python(PySpark案例实战)

为什么要学习PySpark&#xff1f; Spark对Python语言的支持&#xff0c;重点体现在&#xff0c;Python第三方库&#xff1a;PySpark之上。 PySpark是由Spark官方开发的Python语言第三方库。 Python开发者可以使用pip程序快速的安装PySpark并像其它三方库那样直接使用。 PySp…

小谈设计模式(1)—总序

小谈设计模式&#xff08;1&#xff09;—总序 开始操作设计模式总论设计模式是什么组成要素模式名称问题描述解决方案效果描述 设计模式有什么作用提供可重用的解决方案提高代码的可读性和可维护性促进代码的可扩展性提高代码的灵活性和可重用性促进团队合作和沟通作用总结 为…

基于SpringBoot的新闻管理系统

基于SpringBoot的新闻管理系统【附源码文档】、前后端分离系统 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 前台 首页新闻信息校园论坛留言交流个人中心 后台 个人中心用…

报错:数组明明有内容但打印的length是0,学会使用 async 和 await 解决问题

文章目录 一、问题二、分析三、解决1.将异步改为同步2.设置延迟 一、问题 在日常开发中&#xff0c;for 循环遍历调用接口&#xff0c;并将接口返回的值进行拼接&#xff0c;即push到一个新的数组中&#xff0c;但是在for循环内部是可以拿到这个新的数组&#xff0c;而for循环…

“投资教父”熊晓鸽老了,IDG光环不再

作者 | 鸠白 艺馨 排版 | Cathy 监制 | Yoda 出品 | 不二研究 2017年&#xff0c;世界互联网大会上&#xff0c;“投资教父”熊晓鸽问映客的创始人&#xff1a;“今年你们利润能有多少&#xff1f;” 对方笑答&#xff1a;“5个亿吧&#xff01;” “才五个亿&#xff1f…

产品MC动画宣传片制作团队安排

在产品MC动画宣传片的制作过程中&#xff0c;通常需要组建一个专业的团队&#xff0c;以确保各个方面的工作能够高效完成。以下是一个常见的产品MC动画宣传片制作团队的安排&#xff1a; 1.制片人&#xff08;Producer&#xff09;&#xff1a;负责项目的整体策划和管理&#…

华为云云耀云服务器L实例评测|有关华为云云耀云服务器L实例你可能不知道的事情

前言 最近华为云推出了华为云云耀云服务器L实例。主打一个轻量级云服务器&#xff0c;即开即用&#xff0c;轻松运维&#xff0c;开启简单上云第一步。具有智能不卡顿&#xff0c;价优随心用&#xff0c;上手更简单&#xff0c;管理特省心。 在推出的第一时间我就买了一台来耍…