RT-Thread 内存管理(学习一)

news2024/11/16 23:38:52

内存管理

在计算系统中,通常存储空间可以分为两种:内部存储空间外部存储空间

内部存储空间通常访问速度比较快能够按照变量地址随机访问,也就是我们通常所说的RAM随机存储器),可以把它理解为电脑的内存

外部存储空间内所保存的内容相对来说比较固定,即使掉电后数据也不会丢失,也就是通常所讲的ROM只读存储器),可以把它理解为电脑的硬盘

计算机系统中,变量、中间数据一般存放在RAM中,只有在实际使用时才将它们从RAM调入到CPU中进行运算。

一些数据需要的内存大小需要在程序运行过程中根据实际情况确定,这就要求系统具有对内存空间进行动态管理的能力,在用户需要一段内存空间时,向系统申请,系统选择一段合适的内存空间分配给用户,用户使用完毕后,再释放回系统,以便系统将该段内存空间回收再利用。

内存管理的功能特点

由于实时系统中对时间的要求非常严格,内存管理往往要比通用操作系统要求苛刻得多:

  1. 分配内存的时间必须是确定的。一般内存管理算法是根据需要存储的数据的长度在内存中去寻找一个与这段数据相适应的空闲内存块,然后将数据存储在里面。而寻找这样一个空闲内存块所耗费的时间是不确定的,因此对于实时系统来说,这就是不可接受的,实时系统必须要保证内存块的分配过程在可预测的确定时间内完成,否则实时任务对外部事件的响应也将变得不可确定。
  2. 随着内存不断被分配和释放,整个内存区域会产生越来越多的碎片(因为在使用过程中,申请了一些内存,其中一些释放了,导致内存空间中存在一些小的内存块,但因为它们地址并非连续,不能组成一块连续的完整内存块,会使得程序不能申请到大的内存。)对于通用系统来说,这种不恰当的内存分配算法可以通过重新启动系统来解决(每个月或者数个月进行一次),但是对于那些需要常年不间断地工作于野外的嵌入式系统来说,就变得让人无法接受了。
  3. 嵌入式系统的资源环境也是不尽相同,有些系统的资源比较紧张,只有数十KB的内存可供分配,而有些系统则存在数MB的内存,如何为这些不同的系统,选择适合它们的高效率的内存分配算法,就将变得复杂化。

RT-Thread操作系统在内存管理上,根据上层应用及系统资源的不同,有针对性地提供了不同的内存分配管理算法。
总体上可分为两类:内存堆管理与内存池管理,而内存堆管理又根据具体内存设备划分为三种情况:

  1. 针对小内存块的分配管理(小内存管理算法);
  2. 针对大内存块的分配管理(slab管理算法);
  3. 针对多内存堆的分配情况(memheap管理算法)。

内存堆管理

内存堆管理用于管理一段连续的内存空间。

在这里插入图片描述
RT-Thread将“ZI段结尾处”到内存尾部的空间用作内存堆。

内存堆可以在当前资源满足的情况下,根据用户的需求分配任意大小的内存块。
而当用户不需要再使用这些内存块时,又可以释放回堆中共其它应用分配使用。

小内存管理算法主要针对系统资源比较少,一般用于小于2MB内存空间的系统。

小内存管理算法

小内存管理算法是一个简单的内存分配算法。
初始时,它是一块大的内存。当需要分配内存块时,将这个大的内存块上分割出相匹配的内存块,然后把分割出来的空闲内存块还回给堆管理系统中。每个内存块都包含一个管理用的数据头,通过这个头把使用块与空闲块用双向链表的方式链接起来。
在这里插入图片描述
每个内存块(不管是已分配的内存块还是空闲的内存块)都包含一个数据头,其中包括:

  1. magic:变数(或称为幻数),它会被初始化成0x1ea0(即英文单词heap),用于标记这个内存块是一个内存管理用的内存数据块;实质也是一个内存保护字:如果这个区域被改写,那么也就意味着这块内存块被非法改写(正常情况下只有内存管理器才会去碰这块内存)。
  2. used:指示出当前内存块是否已经分配。
    内存管理的表现主要体现在内存的分配与释放上。

在这里插入图片描述
空闲链表指针lfree初始指向32字节的内存块。当用户线程要求再分配一个64字节的内存块时,但此lfree指针指向的内存块只有32字节,并不能满足要求,内存管理器会继续寻找下一内存块,当找到再下一块内存块,128 字节时,它满足分配的要求。
因为这个内存块比较大,分配器将此内存块进行拆分,余下的内存块(52字节)继续留在lfree链表中。

另外,在每次分配内存块前,都会留出 12 字节数据头用于 magic、used 信息及链表节点使用。返回给应用的地址实际上是这块内存块 12 字节以后的地址,前面的 12 字节数据头是用户永远不应该碰的部分(注:12 字节数据头长度会与系统对齐差异而有所不同)。

释放时则是相反的过程,但分配器会查看前后相邻的内存块是否空闲,如果空闲则合并成一个大的空闲内存块。

内存堆配置和初始化

在使用内存堆时,必须要在系统初始化的时候进行堆的初始化,可以通过下面的函数接口完成:

void rt_system_heap_init(void* begin_addr, void* end_addr);

这个函数会把参数 begin_addr,end_addr 区域的内存空间作为内存堆来使用。

分配和释放内存块

void *rt_malloc(rt_size_t nbytes);

rt_malloc函数会从系统堆空间中找到合适大小的内存块,然后把内存块可用地址返回给用户。

  • nbytes:需要分配的内存块的大小,单位为字节。
  • 分配的内存块地址:成功。
  • RT_NULL:失败。

对rt_malloc的返回值进行判空是非常有必要的。
应用程序使用完从内存分配其中申请的内存后,必须及时释放,否则会造成内存泄漏。

int *pi;
pi = rt_malloc(100);
if(pi == NULL)
{
	rt_kprintf("malloc failed\r\n");
}

rt_free函数会把释放内存还给堆管理器中。
在调用这个函数时用户需传递待释放的内存块指针。

重分配内存块

在已分配内存块的基础上重新分配内存块的大小(增加或缩小),可以通过下面的函数接口完成:

void *rt_realloc(void *rmem,rt_size_t newsize);

在进行重新分配内存块时,原来的内存块数据保持不变(缩小的情况下,后面的数据被自动截断)。

  • rt_realloc函数用于修改一个原先已经分配的内存块的大小。使用这个函数,你可以使一块内存扩大或缩小。若用于扩大一个内存块,那么这块内存原先的内容依然保留,新增加的内存添加到原先内存块的后面,新内存并未以任何方式进行初始化。如果它用于缩小一个内存块,该内存尾部的部分内存便被拿掉,剩余部分内存的原先内容依然保留。
  • 如果原先的内存块无法改变大小,rt_realloc将分配另一块正确大小的内存,并把原先那块内存的内容复制到新的块上。因此,在使用rt_realloc之后,就不能再使用指向旧内存块的指针,而是应该改用rt_realloc所返回的新指针。

分配多内存块

从内存堆中分配连续内存地址的多个内存块。

void *rt_calloc(rt_size_t count, rt_size_t size);
  • count:内存块数量
  • size:内存块容量
  • 返回:指向第一个内存块地址的指针,成功,并且所有分配的内存块都被初始化成0。RT_NULL:分配失败。

设置内存钩子函数

在分配内存块过程中,用户可设置一个钩子函数,调用的函数接口如下:

void rt_malloc_sethook(void (*hook)(void *ptr, rt_size_t size));

设置的钩子函数会在内存分配完成后进行回调。
回调时,会把分配到的内存块地址和大小作为入口参数传递进去。

在释放内存时,用户可设置一个钩子函数,调用的函数接口如下:

void rt_free_sethook(void (*hook)(void *ptr));

设置的钩子函数会在调用内存释放完成前进行回调。回调时,释放的内存块地址会作为入口参数传递进去(此时内存块并没有被释放)。

总结

动态内存使用总结:

  • 检查从rt_malloc函数返回的指针是否为NULL
  • 不要访问动态分配内存之外的内存
  • 不要向rt_free传递一个并非由rt_malloc函数返回的指针
  • 在释放动态内存之后不要再访问它
  • 使用sizeof计算数据类型的长度,提高程序的可移植性

常见的动态内存错误:

  • 对NULL指针进行解引用
  • 对分配的内存进行操作时越过边界
  • 释放并非动态分配的内存
  • 释放一块动态分配的内存的一部分(rt_free(ptr+4))
  • 动态内存被释放后继续使用

内存碎片:频繁地调用内存分配和释放接口会导致内存碎片,一个避免内存碎片的策略是使用内存池+内存堆混用的方法。

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

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

相关文章

设备上架与调试步骤项目篇

1.设备又哪些常见的调试方法? 2.设备开箱 -> 使用的步骤是什么? 3.开局新设备都要设置哪些功能? -- 工程师:架构设计 项目实施 故障排查 -- 调试设备: -- 1.WEB界面 - 界面调试 - 内容比较少的 主要项目 …

一文从0到1手把手教学UI自动化测试之数据驱动!

在UI的自动化测试中,我们需要把测试使用到的数据分离到文件中,如果单纯的写在我们的测试模块里面,不是一个好的设计,所以不管是什么类型的自动化测试,都是需要把数据分离出来的。当然分离到具体的文件里面,…

基于YOLOv5的工地安全帽、口罩检测系统

目录 1,YOLOv5模型原理介绍 1.1 输入侧 1.1.1 数据增强 1.1.2 自适应锚框计算 1.1.3 自适应图片缩放 1.2 Backbone 1.3 Neck 1.4 输出端 2 , 基于YOLOv5的工地安全帽、口罩检测系统实现流程 2.1 整体项目 2.2 代码展示 2.3 效果展示 1&a…

VulnHub Mercury

//nmap命令大全 -sT TCP (全)连接扫描,准确但留下大量日志记录-sS TCP SYN (半)扫描,速度较快,不会留下日志-sP扫描存活主机-pn 不检测主机存活,不进行ping-po 扫描之前不进行ping-O 查看目标主机系统版本-sV 探测服务版本-A 全面扫描 一、修…

C++day01(QT简介、C++)

今日任务&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;int main() {/** 输入字符串统计大写、小写、数字、空格以及其他字符的个数**/string s;cout << "请输入一个字符串" << endl;//cin >> s;getline(cin,s);i…

【数据分析】时间序列

UTC时间&#xff1a;时间戳是以格林威治时间1970年01月01日00时00分00秒为基准计算所经过时间的秒数&#xff0c;是一个浮点数。Python的内置模块time和datetime都可以对时间格式数据进行转换&#xff0c;如时间戳和时间字符串的相互转换。 报错记录&#xff1a;AR has been re…

【C++设计模式之组合模式:结构型】分析及示例

简介 组合模式是一种结构型设计模式&#xff0c;它能够将对象组合成树形结构以表示“整体-部分”的层次结构&#xff0c;并且能够使用相同的方式处理单个对象和组合对象。组合模式使得客户端可以一致地处理单个对象和组合对象&#xff0c;无需关心具体的对象类型。 组合模式将对…

一、Excel VBA 是个啥?

Excel VBA 从入门到出门一、Excel VBA 是个啥&#xff1f;二、Excel VBA 简单使用 &#x1f44b;Excel VBA 是个啥&#xff1f; ⚽️1. Excel 中的 VBA 是什么&#xff1f;⚽️2. 为什么 VBA 很重要&#xff1f;⚽️3. 是否有无代码方法可以在 Excel 中实现工作流程自动化&…

QT基础入门——界面布局和常用控件(四)

前言&#xff1a; 所谓 GUI 界面&#xff0c;归根结底&#xff0c;就是一堆组件的叠加。我们创建一个窗口&#xff0c;把按钮放上面&#xff0c;把图标放上面&#xff0c;这样就成了一个界面。在放置时&#xff0c;组件的位置尤其重要。我们必须要指定组件放在哪里&#xff0c…

2023-IDEA插件推荐

CamelCase 链接 https://plugins.jetbrains.com/plugin/7160-camelcase https://github.com/netnexus/camelcaseplugin 介绍 提供下划线、驼峰等代码风格的切换。快捷键是⇧ ⌥ U / Shift Alt U GsonFormatPlus 链接 https://plugins.jetbrains.com/plugin/14949-gs…

比较好用的在线项目管理系统推荐

好的项目管理系统首先要能满足你在管理项目中的要求&#xff0c;不同的团队规模、不同的项目对项目管理的要求都是不一样的。其次&#xff0c;引入项目管理系统的本身是为了提高管理和协作的效率&#xff0c;因此工具应该是要简单易用的&#xff0c;很多企业引入工具之后形同虚…

十、pygame小游戏开发

目录 一、安装pygame二、pygame快速入门2.1 坐标系认识2.2 创建游戏主窗口2.3 实现图像绘制2.4 游戏循环和游戏时钟2.5 简单动画实现的实现2.6 监听事件2.7 精灵和精灵组三、游戏框架搭建3.1 实现飞机大战主游戏类3.2 完成游戏初始化部分3.3 使用常量代替固定的数值3.4 完成游戏…

VulnHub BREAKOUT

一、信息收集 1.端口扫描 nmap -sS -A 192.168.103.178.24发现开发了80、10000、20000 以及有smb协议 2.查看80端口 右击查看源代码&#xff0c;发现尾部有个密文加密 一看就是 Brainfuck/Ook! 加密&#xff0c;解得&#xff1a;.2uqPEfj3D<Pa-3 3.查看10000端口 是个登…

项目需求分析5大常见问题及解决方案

需求分析过程中&#xff0c;往往容易导致需求不准确和不完整&#xff0c;引起需求频繁变更&#xff0c;导致项目进度延误和成本增加&#xff1b;而需求分析的误解问题&#xff0c;导致交付产品无法满足客户期待&#xff0c;降低用户满意度和资源浪费。 那么在需求分析中&#x…

buuctf-[WUSTCTF2020]CV Maker 文件上传漏洞

打开环境 随便登录注册一下 进入到了profile.php 其他没有什么页面&#xff0c;只能更换头像上传文件&#xff0c;所以猜测是文件上传漏洞 上传一句话木马看看 <?php eval($_POST[a]);?>回显 搜索一下 添加文件头GIF89a。上传php文件 查看页面源代码&#xff0c;看…

使用python利用merge+sort函数对excel进行连接并排序

好久没更新了&#xff0c;天天玩短视频了。现在发现找点学习资料真的好难。 10.1期间偶然拿到一本书 本书是2022年出版的&#xff0c;看了一下不错&#xff0c;根据上面的案例结合&#xff0c;公司经营整合案例&#xff0c;分享一下。 数据内容来源于书中内容&#xff0c;仅供…

Dubbo3应用开发—Dubbo3注册中心(zookeeper、nacos、consul)的使用

Dubbo3注册中心的使用 zookeeper注册中心的使用 依赖引入 <dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-dependencies-zookeeper-curator5</artifactId><version>${dubbo.version}</version><type>p…

MySQL Cluster

文章目录 1.简介2.组成参考文献 1.简介 MySQL Cluster 是官方推出的基于 NDB&#xff08;Network DataBase&#xff09;存储引擎的高可用和可伸缩的分布式数据库系统。 以下是 MySQL NDB Cluster 的主要特点和能力&#xff1a; 高可用&#xff1a;MySQL Cluster 具有内置的高…

python+selenium实现UI自动化(入门篇)

一、基础准备。 python环境安装&#xff0c;参考&#xff1a;CSDN pycharm安装&#xff0c;参考&#xff1a;CSDN 谷歌浏览器驱动配置&#xff0c;参考&#xff1a;CSDN二、新建pycharm项目 截图中&#xff0c;上面是项目地址&#xff08;可以提前在指定位置创建文件夹&#xf…

TenDB Cluster 简介

文章目录 1.简介2.TSpider3.TenDB4.Tdbctl5.TenDB Cluster Operator参考文献 1.简介 TenDB Cluster 是腾讯游戏 CROS DBA 团队提供的 MySQL 分布式关系型数据库解决方案。主要特点包括&#xff1a;透明分库分表、高可用的 MySQL 集群服务&#xff0c;透明及在线的扩容及缩容&a…