当前位置:网站首页>第21章 内存管理
第21章 内存管理
2022-07-29 18:19:00 【51CTO】
一、内存管理的基本概念
存储空间分:内部存储空间(RAM)和外部存储空间;
内部存储空间访问速度较快,能够按照变量地址随机访问;
外部存储空间保存的数据比较固定,掉电后都不会丢失
FreeRTOS有5种内存管理算法:heap_1.c、heap_2.c、heap_3.c、heap_4.c、heap_5.c、
内存管理需要考虑的因素:可靠性、内存申请时间、产生的内存碎片
二、内存管理的应用场景
内存管理的主要工作是动态划分并管理用户分配好的内存区间,在用户需要使用大小不等的内存块的场景中使用,需要分配内存时,通过操作系统内存申请函数索取指定大小内存块,用完后,通过动态内存释放函数归还所占用的内存
三、内存管理方案详解
通用接口

1.第一种方式heap_1.c
heap_1提供的内存管理机制是,只能申请内存而不能进行内存释放,且申请内存的时间是一个常量;内存利用率不高,但不会产生碎片
使用两个静态变量进行管理:xNextFreeByte,空闲内存的偏移量;pucAligendHeap指向对齐后的内存堆起始地址,初始时不一定是&ucHeap[0],因为ucHeap[0]不一定是8byte对齐,pucAligendHeap是对齐后的起始地址


(1)内存申请:需求内存的大小进行对齐(如8字节对齐的,申请30byte的时候,就会申请到32byte)-----调度器挂起-----申请内存---更新空闲内存偏移量----恢复调度器-----返回申请的地址


(2)其他函数:
vPortFree()没有用上,该方式的内存管理,只申请,不释放
vPortInitialiseBlocks:函数仅将xNextFreeByte设置为0
xPortGetFreeHeapSize:返回未使用的内存大小,用总内存大小,减去xNextFreeByte
2.heap_2.c
采用最佳匹配算法(best fit algorithm),从可申请内存中选出大小最匹配的内存块,且支持内存释放,但是不能把相邻的两个小内存块合并成一个大的内存块,每次申请内存大小不固定,而且不会合并,导致非常容易产生碎片
机制:在内存中开辟一个静态数组作为堆的空间,并采用链表记录空闲内存块

(1)内存初始化prvHeapInit()
分配链表头,链表尾,可用内存空间,初始化后,链表由3个节点:

(2)内存申请函数pvPortMalloc
采用最佳匹配算法管理内存:内存块空闲链表按照内存块大小升序排列,每个节点保存一个空闲内存块的信息,也就是每个节点的内容是内存块信息+空闲内存;
从链表中查找合适的大小的节点

找到合适节点pxBlock后,从链表中移除,

加入pxBlock节点的内存大小使用不完,将剩下的内存插入到链表中


(3)内存释放
根据需要释放的内存地址找到节点起始地址,起始地址是释放的内存地址减去节点信息数据地址,最后插入空闲链表

3.heap_3.c
heap_3只是简单的封装了标准C库里的malloc和free函数,在启动文件里已经配置好

4.heap_4.c
heap_4方案是在heap_2方案上,添加了合并算法,即将(地址)相邻的空闲内存块进行合并,使之变成更大的块,从而减少内存碎片
内存空闲块链表以内存块起始地址大小进行排序(heap_2是按照块大小升序排序)
(1)内存申请pvPortMalloc
从链表头开始遍历找到合适内存块,取出需要的内存大小部分返回,并将该内存块大小的最高为置1标记为已用,剩下内存块组成新的空闲块,按照空闲内存块起始地址大小插入空闲块链表

新空闲内存块插入链表

内存块大小最高位置1标志内存块已用

(2)初始化prvHeapInit(),链表头指向的是对齐后的堆起始地址

(3)释放内存
根据需要释放的内存的地址,反推该内存所在的节点地址,并且根据节点大小的最高位是否为1标记已用,为1则清除标记然后插入链表中


(4)插入链表
链表是以节点地址升序排序,因此找到链表节点后,插入,并判断新插入的前后节点是否为空,为空则进行合并


5.heap_5.c
heap_5方案与heap_4方案类似,只是heap_5的方案允许内存堆跨越非连续的内存区,即允许在不连续的内存堆里实现内存分配。
(1)初始化vPortDefineHeapRegions
将内存堆区域的起始地址和内存堆大小当道HeapRegion_t的数组中

将数组元素用链表连接起来,每个数组元素是一个节点

(2)内存申请,释放均与Heap_4方案一样
学习心得:
1.内存管理:根据不同的策略进行内存的分配,回收,用链表管理空闲内存块
2.5种分配方案:
(1)heap_1:最简单,只申请,不释放
(2)heap_2:相对也很简单,可以申请,也可以释放,内存块被切割之后,不会合并,空闲内存块链表以空闲内存块大小升序排序
(3)heap_3:调用标准C库的Malloc和free函数,堆内存大小在启动文件的汇编定义startup_stm32f10x_hd.lst
(4)heap_4:比较完美的内存管理方案,可申请,可释放,释放内存的时候可以将前后连续空闲的内存块合并,编程更大的内存块,空闲内存块链表以内存块起始地址大小升序排序
(5)heap_5:在heap_4方案上,允许不连续的内存堆进行分配,分配方式与heap_4是相同的,堆内存初始化方法不样,需要将进入管理的内存以数组形式列举出来,并添加到队列中
问题:
1.堆内存与栈内存
2.RAM和SDRAM
边栏推荐
- 国产钡铼分布式IO模块如何与西门子PLC Profinet通讯
- [Code Hoof Set Novice Village 600 Questions] Find the distance between two points in the space rectangular coordinate system
- 整体系统地认识网络安全与发展
- 解决 @RefreshScope 导致定时任务注解 @Scheduled 失效
- 已经删除了的SQL节点,有没有办法恢复
- 431页14万字政府信息化管理平台解决方案
- KubeMeet 报名 | 「边缘原生」线上技术沙龙完整议程公布!
- R语言时间序列数据可视化: 使用plot函数可视化单序列时间序列数据、多序列时间序列数据并指定不同时间序列的线条类型(lty)
- Canal实现Mysql数据增量同步更新至Mysql/Redis
- Setting right:0 after sticky positioning does not take effect
猜你喜欢
随机推荐
R语言时间序列数据提取:使用xts包的first函数提取时间序列中最前面一个月的数据(first 1 month)
【MySQL】如何向mysql数据库插入当前时间
swin-transformer初步理解
P5514 [MtOI2019]永夜的报应(位运算)
leetcode:36. 有效的数独
SK海力士工厂发生氢氟酸泄漏,3名工人受伤!官方称不会影响生产
593. 有效的正方形 改善丑陋的代码
Zigbee组网控制流程
制作文件上传进度条
pkg_resources.DistributionNotFound: The 'pip==1.4' distribution was not found and is required
2022开放原子全球开源峰会OpenAnolis分论坛圆满落幕
Google Cloud X Kyligence|如何从业务视角管理数据湖?
sticky定位后设置right:0不生效
分批数据遍历的优化
亿级用户背后的字节跳动云原生计算最佳实践
最近很郁闷
机器学习:知道模型评估中的SSE、“肘”部法、SC系数和CH系数的实现原理
原理银行一直在收我利息!!!
R语言ggplot2可视化绘制条形图(bar plot)、使用gghighlight包突出高亮条形图中的特定条形(highlight specific bar plot)
500强企业研发效能提升课,今晚开课啦!









