FreeRTOS学习:内存管理

news2024/10/2 10:23:50

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.coloradmin.cn/o/2065569.html

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

相关文章

基于Django的停车场车辆出入管理系统,可识别车牌图片

研究背景 随着城市化进程的加快,车辆数量不断增加,停车场的管理成为一个日益重要的课题。传统的停车场管理系统依赖人工登记和监控,不仅效率低下,而且容易出现疏漏和错误,难以满足现代社会对停车场管理智能化、高效化…

Scrum敏捷开发高效实践课程:面向企业团队的系统化训练,旨在提升研发效率,优化项目管理,推动企业敏捷化发展。

课程简介: Scrum 是一种广泛应用的敏捷开发方法,用于项目管理和产品研发。该课程为期两天,专为研发管理者、项目经理、产品经理和研发团队设计。通过案例讲解和沙盘演练,学员将深入理解Scrum的核心理念,如产品价值驱动…

基于x86 平台opencv的图像采集和seetaface6的人脸跟踪功能

目录 一、概述二、环境要求2.1 硬件环境2.2 软件环境三、开发流程3.1 编写测试3.2 配置资源文件3.2 验证功能一、概述 本文档是针对x86 平台opencv的图像采集和seetaface6的人脸跟踪功能,opencv通过摄像头采集视频图像,将采集的视频图像送给seetaface6的人脸跟踪模块从而实现…

谢广坤:愿意说话你自己起个头行不?刘能:我起头不费劲吗!

谢广坤:愿意说话你自己起个头行不?刘能:我起头不费劲吗! --小品《欢乐农家》(赵家班、上)的台词与解说 刘能:大脚 谢大脚:咋的了这是 大过年的 刘:脚崴了 大脚&…

Godot自定义快捷键(配置视图快捷键)

如图 这个没啥技术,但是配置快捷键的时候有讲究如图 选择万国码并且将前后左右下上(顶底)分别配置为123456。汝等自管记好,今后自有妙用(哈哈)效果如图

饮水机开水前加入童锁判断

饮水机开水前加入童锁判断 引言 饮水机加入童锁, 是配合红外线, 进行防误触检测. 我们模仿红外线检测杯子, 加入童锁变量, 这个变量是人工控制的, 开水前,检测一下童锁,如果童锁锁住 , 则不能开水, 我们只需要修改一下底层即可. 本博客修改完的代码工程: https://wwyz.lanzou…

《计算机操作系统》(第4版)第6章 输入输出系统 复习笔记

第6章 输入输出系统 一、I/O 系统的功能、模型和接口 1.I/O 系统的基本功能 (1)隐藏物理设备的细节。 (2)与设备的无关性。 (3)提高处理机和I/O 设备的利用率。 ( 4 ) 对I/O 设备进行控制。 (5)确保对设备的正确共享。 (6)错误处理。 2.I/O 系统的层次结构和模型 (…

21.1 Netty介绍及服务搭建

21.1 基于Netty实现聊天 一. 章节概述二. `Netty`介绍三. 阻塞与非阻塞1. 阻塞与非阻塞简介2. BIO同步阻塞3. NIO同步非阻塞4. AIO异步非阻塞IO5. 异步阻塞IO(用的极少)6. 总结四. Netty三种线程模型1. 单线程模型2. 多线程模型3. 主从线程模型五. 构建Netty服务器************…

【传输层协议】UDP协议 {端口号的范围划分;UDP数据报格式;UDP协议的特点;UDP的缓冲区;基于UDP的应用层协议}

一、再谈端口号 1.1 端口号标识网络进程 如何通过端口号找到主机上的网络进程? 在socket编程中bind绑定是最为重要的一步:他将套接字与指定的本地 IP 地址和端口号关联起来,这意味着指定的套接字可以接收来自指定 IP 地址和端口号的数据包…

跟李沐学AI:转置卷积

定义 卷积不会增大输入的高宽,通常卷积层后高宽不变或减半。转置卷积则可以用来增大输入的宽高。 转置卷积是一种卷积,它将输入和核进行了重新排列,通常用作上采用。 如果卷积将输入从变为,同样超参数的情况下,转置…

坐标大连!提交EI、Scopus、知网检索!第五届经济管理与大数据应用国际学术会议(ICEMBDA 2024)

合作ACM出版-EI稳检索 高录用,快见刊! 管理、经济、金融、计算机相关主题均可投稿 目前仍有口头汇报名额,如有需要请尽快报名 重要信息 会议官网:www.icembda.org 会议时间:2024年10月25日-27日 会议地点&#x…

20.缓存的更新策略

定义 缓存中的旧数据与数据库不一致。 缓存更新策略的类型 1.内存淘汰,利用redis的内存淘汰机制,当内存不足时自动淘汰部分数据。下次查询时更新缓存。redis默认开启了此机制。这种保证数据的一致性差。 2.超时剔除,给缓存数据添加TTL时间…

保证MQ的高可用性:RabbitMQ为例

保证MQ的高可用性:RabbitMQ为例 一、单机模式二、普通集群模式三、镜像集群模式 💖The Begin💖点点关注,收藏不迷路💖 消息队列(MQ)在软件开发中至关重要,其高可用性关乎系统稳定。R…

48、Python之模块和包:当导入模块时,Python解释器做了什么

引言 上一篇文章中,我们简单介绍了各种导入模块的方法,并通过代码演示了模块被导入之前的模块查找的路径解析过程,但是,只是局限在了加载模块之前。 今天这篇文章,打算把整个模块导入的全流程进行梳理,从…

Windows上传Linux文件行尾符转换

Windows上传Linux文件行尾符转换 1、Windows与Linux文件行尾符2、Windows与Linux文件格式转换 1、Windows与Linux文件行尾符 众所周知,Windows、Mac与Linux三种系统的文件行尾符不同,其中 Windows文件行尾符(\r\n): L…

【初阶数据结构题目】40. 计数排序

计数排序 计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。 操作步骤: 统计相同元素出现次数 根据统计的结果将序列回收到原来的序列中 思路: 例如:{6,1,2,9,4,…

书生模型实战L1---OpenCompass 评测

书生模型实战系列文章目录 第一章 入门岛L0(Linux) 第二章 入门岛L0(python) 第三章 入门岛L0(Git) 第四章 基础岛L1(书生全链路开源介绍) 第五章 基础岛L1(Demo&#x…

【计算机三级-数据库技术】操作题大题(第六套)

第六套操作题 第46题 假定要建立一个学校科研项目管理的信息系统,需要管理如下信息: 教师:教师编号、教师姓名; 项目:项目编号、项目名称、资助额: 学生:学生编号、学生姓名、学位&#xff0c…

Spring底层机制环境搭建

文章目录 1.模块创建和依赖引入1.聚合模块,下面有一个myspring2.查看父模块是否管理了子模块3.myspring模块引入基本包 2.进行环境搭建1.目录概览2.UserController.java3.UserService.java4.UserDao.java5.AppMain.java6.beans.xml7.测试8.配置UserController.java为…

教程3_单元层次结构1

单元层次结构是指通过将多个单元嵌套使用,形成具有层次结构的设计。每个单元可以包含其他单元的实例,这些实例称为“子单元”,而包含这些子单元的单元称为“父单元”。这种结构使得复杂设计变得模块化和可复用。 1、创建并使用单元实例 创建…