动态分配
本篇开始说一个耳朵听起老茧的概念 动态分配,将分成上下两篇,本篇为上篇,看完能快速理解下篇鸿蒙内核源码对动态内存的具体实现。
- 鸿蒙内核源码分析(TLFS算法) 结合图表从理论视角说清楚 TLFS 算法
- 鸿蒙内核源码分析(内存池管理) 结合源码说清楚鸿蒙内核动态内存池实现过程,个人认为这部分代码很精彩,简洁高效,尤其对空闲节点和已使用节点的实现令人称奇。
TLFS 原理
TLSF(Two-Level Segregate Fit) 是一种用于实时操作系统的内存分配算法,用两级结构对空闲块按大小进行划分,采用两级链表/索引的方式来加快查找。
把上图看懂基本能明白 TLFS 的原理,请尝试自己先理解一遍再看本篇。
解读
- 为方便理解 ,将上图做成(表一),中间过程请查看图表变化
- 右边为第一级链表
First List
(简称fl
)。将空闲内存块的大小根据2
的幂进行分类,如(32、64、128、…), 这跟伙伴算法很类似,伙伴算法是物理内存的分配算法,这样做的好处是防止外部碎片化,是否空闲用位图标识 FL_bitmap | 一维数组,0011
代表[32-64]、[64-128]
这个区间有内存可以申请,例如: malloc(37) 时,查到在区间[32-64]
中,为1
代表本次可能可以申请到内存,但具体行不行得进入第二级查看。 - 中间为第二级链表
Second List
(简称sl
)。第二层链表在第一层的基础上,按照一定的间隔,线性分段,图中将其分成8
等份,对于[32-64]
来说1/8
为4
,对于[64 - 128]
来说1/8
为8
,可以确定的是等份也是2
的倍数,同样是否空闲用位图标识SL_bitmaps[] | 二维数组 ,每个bit代表是否空闲,图中代表[36 - 39]
有内存可供分配,再查看其空闲链表发现真正可供分配的空间有两块,38 和 36
,自然将38
给 malloc(37) 返回,此时空闲链表中还剩36
节点 ,所以 一二级位图数据不会有任何的变化。 - 左边为空闲链表块,上面挂
fl
,sl
都为1
时的空闲内存块,块大小为区间范围值,图中有两个空闲块38b --> 36b
,109b --> 104b
,在实际运行过程往往出现同样大小的内存块例如38b --> 36b--> 36b
申请过程
用二次申请说明详细过程
- malloc(37) ,发现值在区间
[32-64]
并对应fl
的位图为1
,说明sl
中肯定会有一个1
,但并不能保证能申请到。得细看第二步sl
发现区间[36 - 39]
的位图为1
,说明空闲链表中肯定会有一块内存,,但也不能保证大小适合37
。再看最后一步,发现有两块内存38b --> 36b
,只有38b
符合,于是 malloc(37) 的结果是获得了一块大小38b
的内存块,相差的一个1b
称为内部碎片,这种碎片无法避免。将(表一)更新为(表二)
- malloc(50),同样落在
[32-64]
查看fl
的位图为1
,查看第二步sl
只有[36 - 39]
的位图为1
,而 50 > 39,不能满足所以没必要看第三步,得返回第一步往上走发现[64-128]
的fl
的位图为1
,50 < 64 说明 malloc(50) 这次肯定能申请到内存了,查看[64-128]
对应的sl
发现[104-111]
的位图为1
,到第三步发现有109b --> 104b
两块,选择其中更小104b
的块切割成50
,54
两小块,此时要对54
处理挂入空闲链表,54
处于fl = [32-64]
,sl = [52-55]
区间,地址为: 0x6838+50=0x686A 。所以将[52-55]
区间位图置为1
,并挂入空闲链表。将(表二)更新为(表三)
注意此时[32-64]
的二级位图变成了 00100010 有两个1
释放过程
同样用二次释放说明详细过程
- free(0x3457) 从地址可知正是上面的 malloc(37)的内存,与分配切割相对应的是释放有合并的步骤,但malloc(37)虽然申请是
37
,但其实内核记录的内存块大小是38
,所以会找寻地址为 0x3457 + 38 = 0x348F 的地址是否也处于空闲,如果是则合并,由表三可知 并没有 0x348F的空闲块将,而38
位于fl = [32-64]
,sl = [36-39]
区间,所以挂回该空闲链表等待后续再分配使用,由此(表三)更新为(表四)
- free(0x5610) 这里假设内核记录该内存块大小为 0x15,归还的同时会找寻0x5610 + 0x15 = 0x5625 是否有空闲块,发现
sl = [104-111]
有一块109b
空闲块,两块合成一块大小为 109 + 0x15 = 109 + 21 = 130,位于fl = [128-255]
,sl = [128-143]
区间,由此(表四)再更新为(表五)
总结
TLSF(Two-Level Segregate Fit) 有两大优点:
- 实时性,执行速度快,只需查询位图就能知道结果,最多查询两次一级位图,时间复杂度为O(1)。
- 碎片少,浪费少,利用率高,因采用2次幂的方式,切割和合并非常的方便,很少出现外部碎片。
真正的鸿蒙内存动态分配实现过程比这些要复杂些,但有了本文算法基础做铺垫看源码实现会容易很多。
经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?
为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。
《鸿蒙 (Harmony OS)开发学习手册》(共计892页)
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……
开发基础知识:
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……
鸿蒙开发面试真题(含参考答案)
OpenHarmony 开发环境搭建
《OpenHarmony源码解析》
- 搭建开发环境
- Windows 开发环境的搭建
- Ubuntu 开发环境搭建
- Linux 与 Windows 之间的文件共享
- ……
- 系统架构分析
- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……
OpenHarmony 设备开发学习手册
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。