FreeRTOS内存管理
1. 为什么要自己实现内存管理
- 对于内核对象,可以使用时分配,不使用时释放
- C语音的库函数不适应与FreeRTOS:
- 实现过于复杂,占用空间大
- 并非线程安全的
- 运行不确定性:每次运算时间不确定
- 内存碎片化
- 不太编译器配置不同
- 调试难
2. 堆栈
我们经常说的“堆栈”,是两种不同的东西
2.1. 堆
heap就是一块空闲的内存,通过malloc、free来管理
2.2. 栈
stack,函数调用时局部变量保存在栈中,当前的程序环境也保存在栈中,可以充堆中分配一块内存用于栈空间
3. FreeRTOS系统5种内存管理方法
文件在 FreeRTOS/Source/portable/MemMang 下,5个文件对应5中内存管理方法:
3.1. Heap_1
3.1.1. 特点
只实现了pvPortMalloc,没有实现vPortFree,如果程序中不需要删除内核对象,不需要释放内存,那么可以实现heap_1:
- 实现最简单
- 没有碎片问题
- 一些要求非常严格的系统中,不允许使用动态内存,可实现heap_1
3.1.2. 实现原理
- 定义一个大数组
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
/* The application writer has already defined the array used for the RTOS
* heap - probably so it can be placed in a special segment or address. */
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */
- 调用pvPortMalloc调用时,从数组中分配空间
注意:
内存申请时,需要字节对齐处理
–> 在有些处理器中,访问奇地址访问内存会报错
3.2. Heap_2
Heap_2 之所以还保留,只是为了兼容以前的代码。新的设计中,不再推进实现Heap_2。
Heap_2也是在数组上分配内存,和Heap_1不一样的地方在于:
- heap_2使用最佳匹配算法来分配内存
- 支持vPortFree
3.2.1. 数据结构
typedef struct A_BLOCK_LINK
{struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */size_t xBlockSize; /*<< The size of the free block. */
} BlockLink_t;
3.2.2. 内存结构
3.2.3. 最佳匹配算法:
- 假设Heap有3个空闲块:5字节、25字节、100字节
- pvPortMalloc想申请20个字节
- 先找到最小的、能满足要求的内存:25字节
- 把它分为20字节、5字节
- 返回20字节的地址
- 剩下的5字节仍是空闲状态,继续留给后续使用
与Heap_4相比,Heap_2不会合并相邻的空闲内存,所以Heap_2会导致严重的碎片化问题,但是如果申请、分配内存大小都相同的场景下,Heap_2就没有碎片化问题,所以它适合这些场景:频繁窗户删除任务、但任务的栈大小都是相同的。
虽然不再推荐使用Heap_2,但它的效率还是远高于malloc、free.
3.3. Heap_3
Heap_3 使用标准 C 库里的 malloc、 free 函数,C 库里的 malloc、 free 函数并非线程安全的, Heap_3 中先暂停 FreeRTOS 的调度器,再去调用这些函数,使用这种方法实现了线程安全。
3.4. Heap_4
跟 Heap_1、 Heap_2 一样, Heap_4 也是使用大数组来分配内存。Heap_4 使用首次适应算法(first fit)来分配内存。它还会把相邻的空闲内存合并为一个更大的空闲内存,这有助于较少内存的碎片问题。
3.4.1. 首次适应算法
- 假设堆中有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
Heap_5 分配内存、释放内存的算法跟 Heap_4 是一样的。
相比于 Heap_4, Heap_5 并不局限于管理一个大数组:它可以管理多块、分隔开的内存。
在嵌入式系统中,内存的地址可能并不连续,这种场景下可以使用 Heap_5。
既然内存时分隔开的,那么就需要进行初始化:确定这些内存块在哪、多大:
- 在使用 pvPortMalloc 之前,必须先指定内存块的信息
- 使用 vPortDefineHeapRegions 来指定这些信息
怎么指定一块内存?使用如下结构体:
typedef struct HeapRegion
{uint8_t * pucStartAddress; // 起始地址size_t xSizeInBytes; // 大小
} HeapRegion_t;
怎么指定多块内存?使用一个 HeapRegion_t 数组,在这个数组中,低地址在前、高地址在后。
HeapRegion_t xHeapRegions[] =
{{ ( uint8_t * ) 0x80000000UL, 0x10000 }, // 起始地址 0x80000000,大小 0x10000{ ( uint8_t * ) 0x90000000UL, 0xa0000 }, // 起始地址 0x90000000,大小 0xa0000{ NULL, 0 } // 表示数组结束
};
vPortDefineHeapRegions 函数原型如下:
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions );
把 xHeapRegions 数组传给 vPortDefineHeapRegions 函数,即可初始化 Heap_5。
4. Heap接口
4.1. pvPortMalloc/vPortFree
void * pvPortMalloc( size_t xWantedSize );
void vPortFree( void * pv );
4.2. xPortGetFreeHeapSize
size_t xPortGetFreeHeapSize( void );
只有 heap_4、 heap_5 支持此函数。
4.3. xPortGetMinimumEverFreeHeapSize
size_t xPortGetMinimumEverFreeHeapSize( void );
返回:程序运行过程中,空闲内存容量的最小值
只有 heap_4、 heap_5 支持此函数。
4.4. malloc 失败的钩子函数
void * pvPortMalloc( size_t xWantedSize )vPortDefineHeapRegions
相关文章:

FreeRTOS内存管理
1. 为什么要自己实现内存管理 对于内核对象,可以使用时分配,不使用时释放C语音的库函数不适应与FreeRTOS: 实现过于复杂,占用空间大并非线程安全的运行不确定性:每次运算时间不确定内存碎片化不太编译器配置不同调试难 2. 堆栈…...
利用服务工作线程serviceWorker缓存静态文件css,html,js,图片等的方法,以及更新和删除及版本控制
Service Worker 是一种运行在浏览器背后的独立线程,可以用来处理推送通知、后台同步、缓存等任务。以下是使用 Service Worker 来缓存图片的一个基本示例: 1、注册 Service Worker: 首先,你需要在你的 JavaScript 文件中注册 Service Worker。…...

MuMu模拟器安卓12安装Xposed 框架
MuMu模拟器安卓12安装Xposed 框架 当开启代理后,客户端会对代理服务器证书与自身内置证书展开检测,只要检测出两者存在不一致的情况,客户端就会拒绝连接。正是这个原因,才致使我们既没有网络,又抓不到数据包。 解决方式: 通过xposed框架和trustmealready禁掉app里面校验…...

高级数据结构——hash表与布隆过滤器
文章目录 hash表与布隆过滤器1. hash函数2. 选择hash函数3. 散列冲突3.1 负载因子3.2 冲突解决3. STL中的散列表 4. 布隆过滤器4.1 背景1. 应用场景2. 常见的处理场景: 4.2 布隆过滤器构成4.3 原理4.4 应用分析4.5 要点 5. 分布式一致性hash5.1 缓存失效问题 6. 大数…...

【网络】什么是交换机?switch
交换机(Switch)意为“开关”,是一种用于电(光)信号转发的网络设备。以下是关于交换机的详细解释: 一、交换机的基本定义 功能:交换机能为接入交换机的任意两个网络节点提供独享的电信号通路&am…...

软件测试 —— 自动化基础
目录 前言 一、Web 自动化测试 1.什么是 Web 自动化测试 2.驱动 3.安装驱动管理 二、Selenium 1.简单 web 自动化测试示例 2.工作原理 三、元素定位 1.cssSelector 2.XPath 四、操作测试对象 1.点击/提交对象 2.模拟按键输入 3.清除文本内容 4.获取文本信息 5.…...
深入解析 OpenHarmony 构建系统-4-OHOSLoader类
在OpenHarmony操作系统构建过程中,OHOSLoader类扮演着至关重要的角色。这个类负责加载和解析构建配置,生成必要的构建文件,并确保构建过程的顺利进行。本文将深入分析OHOSLoader类的实现细节,揭示其如何管理构建配置,并…...

【Android、IOS、Flutter、鸿蒙、ReactNative 】实现 MVP 架构
Android Studio 版本 Android Java MVP 模式 参考 模型层 model public class User {private String email;private String password;public User(String email, String password) {this.email = email;this.password = password;}public String getEmail() {return email;}…...

排序算法(基础)大全
一、排序算法的作用: 排序算法的主要作用是将一组数据按照特定的顺序进行排列,使得数据更加有序和有组织。 1. 查找效率:通过将数据进行排序,可以提高查找算法的效率。在有序的数据中,可以使用更加高效的查找算法&…...
Pytest从入门到精通
一、pytest单元测试框架 (1)什么是单元测试框架 单元测试是指在软件开发当中,针对软件的最小单位(函数,方法)进行正确性的检查测试。 (2)单元测试框架 java : junit和testng python : unittest和pytest (3)单元测试框架主要做什么? 1.测试发现:从多个文件里面去找到我们测试…...
《C++ 实现生成多个弹窗程序》
《C 实现生成多个弹窗程序》 在 C 编程中,我们可以利用特定的系统函数来创建弹窗,实现向用户展示信息等功能。当需要生成多个弹窗时,我们可以通过循环结构等方式来达成这一目的。 一、所需头文件及函数介绍 在 Windows 操作系统环境下&#…...
react 中 useRef Hook 作用
useRef是一个非常实用的钩子函数 一、访问和操作 DOM 元素 1. 获取 DOM 元素引用 1.1 基本原理 通过 useRef 我们可以直接操作 DOM 元素 1.2 代码示例 import React, { useRef, useEffect } from "react";const InputFocusComponent () > {const inputRef …...

Scala-键盘输入(StdIn)-用法详解
Scala 在 Scala 中,进行 键盘输入 主要通过 scala.io.StdIn 包来实现。 StdIn 提供了几个方法,用于从用户的键盘输入中读取不同类型的数据,如字符串、整数、浮点数等。 常用的输入方法有 readLine()、readInt()、readDouble()、readShort(…...

力扣(LeetCode)283. 移动零(Java)
White graces:个人主页 🙉专栏推荐:Java入门知识🙉 🐹今日诗词:雾失楼台,月迷津渡🐹 ⛳️点赞 ☀️收藏⭐️关注💬卑微小博主🙏 ⛳️点赞 ☀️收藏⭐️关注💬卑微小博主…...
ESP32C3单片机使用笔记---烧录MicroPython
使用MicroPython在ESP32C3单片机上编程,首先需要将MicroPython运行环境烧录到ESP32C3的Flash中去,步骤如下: 1.下载esptool烧录工具,下载地址: https://github.com/espressif/esptool 直接使用git clone git clone…...

Matter1.4重磅来袭,智能家居进入“互联”新纪元
近日,连接标准联盟(CSA)正式宣布推出最新的Matter1.4标准版本,并更新了一系列“史诗级”的增强功能,旨在提升现有智能家居之间的互操作性与兼容性,为智能家居用户带来更流畅的使用体验。 华普微,…...

tdengine学习笔记
官方文档:用 Docker 快速体验 TDengine | TDengine 文档 | 涛思数据 整体架构 TDENGINE是分布式,高可靠,支持水平扩展的架构设计 TDengine分布式架构的逻辑结构图如下 一个完整的 TDengine 系统是运行在一到多个物理节点上的,包含…...

机器学习-36-对ML的思考之机器学习研究的初衷及科学研究的期望
文章目录 1 机器学习最初的样子1.1 知识工程诞生(专家系统)1.2 知识工程高潮期1.3 专家系统的瓶颈(知识获取)1.4 机器学习研究的初衷2 科学研究对机器学习的期望2.1 面向科学研究的机器学习轮廓2.2 机器学习及其应用研讨会2.3 智能信息处理系列研讨会2.4 机器学习对科学研究的重…...

Linux 进程信号的产生
目录 0.前言 1. 通过终端按键产生信号 1.1 CtrlC:发送 SIGINT 信号 1.2 Ctrl\:发送 SIGQUIT 信号 1.3 CtrlZ:发送 SIGTSTP 信号 2.调用系统命令向进程发信号 3.使用函数产生信号 3.1 kill 函数 3.2 raise 函数 3.3 abort 函数 4.由软件条件产…...

CentOS8 在MySQL8.0 实现半同步复制
#原理 MySQL默认是异步的,不要求必须全部同步到从节点才返回成功结果; 同步复制: 用户发请求到代理, 代理收到请求后写/更新数据库写入到二进制日志bin_log, 然后必须等数据发到所有的从节点, 从节点全部收到数据后, 主节点才返回给客户端的成功结果。 弊端: 客…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...

【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...

图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...

uni-app学习笔记三十五--扩展组件的安装和使用
由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...