天天看点

深层剖析鸿蒙轻内核M核的动态内存如何支持多段非连续性内存

摘要:鸿蒙轻内核M核新增支持了多段非连续性内存区域,把多个非连续性内存逻辑上合一,用户不感知底层的不同内存块。

本文分享自华为云社区《鸿蒙轻内核M核源码分析系列九 动态内存Dynamic Memory 补充》,作者:zhushy。

一些芯片片内RAM大小无法满足要求,需要使用片外物理内存进行扩充。对于多段非连续性内存,需要内存管理模块统一管理,应用使用内存接口时不需要关注内存分配属于哪块物理内存,不感知多块内存。

多段非连续性内存如下图所示:

深层剖析鸿蒙轻内核M核的动态内存如何支持多段非连续性内存

鸿蒙轻内核M核新增支持了多段非连续性内存区域,把多个非连续性内存逻辑上合一,用户不感知底层的不同内存块。本文来分析下动态内存模块的支持多段非连续内存的源码,帮助读者掌握其使用。本文中所涉及的源码,以OpenHarmony LiteOS-M内核为例,均可以在开源站点https://gitee.com/openharmony/kernel_liteos_m 获取。接下来,我们看下新增的结构体、宏和对外接口的源代码。

在文件kernel/include/los_memory.h中新增了结构体LosMemRegion用于维护多个非连续的内存区域,包含各个内存区域的开始地址和大小。如下:

需要注意这个结构体的定义需要开启宏LOSCFG_MEM_MUL_REGIONS的情况下才生效,这个宏也是支持非连续内存区域的配置宏,定义在文件kernel/include/los_config.h中。

我们继续看下新增的几个宏函数,定义在文件kernel/src/mm/los_memory.c,代码下下文:

注释讲的比较明白,当开启LOSCFG_MEM_MUL_REGIONS支持非连续内存特性时,会把两个不连续内存区域之间的间隔Gap区域标记为虚拟的已使用内存节点。这个节点当然不能被释放,在内存调测特性中也不能被统计。因为我们只是把它视为已使用内存节点,但其实不是。在动态内存算法中每个内存节点都维护一个指向前序节点的指针,对于虚拟已使用节点,我们把该指针设置为魔术字,来标记它是个内存区域的间隔部分。

⑴处定义了一个魔术字OS_MEM_GAP_NODE_MAGIC,用于表示两个不连续内存区域之前的间隔Gap区域。⑵和⑶处定义2个宏,分别用于设置魔术字,验证魔术字。

本节我们一起分析下非连续性内存的实现算法,及接口实现代码。首先通过示意图了解下算法:

深层剖析鸿蒙轻内核M核的动态内存如何支持多段非连续性内存

集合示意图,我们了解下非连续性内存合并为一个内存池的步骤:

1、把多段内存区域的第一块内存区域调用LOS_MemInit进行初始化

2、获取下一个内存区域的开始地址和长度,计算该内存区域和上一块内存区域的间隔大小gapSize。

3、把内存块间隔部分视为虚拟的已使用节点,使用上一内存块的尾节点,设置其大小为gapSize+ OS_MEM_NODE_HEAD_SIZE。

4、把当前内存区域划分为一个空闲内存块和一个尾节点,把空闲内存块插入到空闲链表。并设置各个节点的前后链接关系。

5、有更多的非连续内存块,重复上述步骤2-4。

新增的接口的接口说明文档见下文,注释比较详细,总结如下:

LOSCFG_MEM_MUL_REGIONS=0:

不支持多段非连续内存,相关代码不使能。

LOSCFG_MEM_MUL_REGIONS=1:

支持多段非连续内存,相关代码使能。用户配置多段内存区域,调用接口

LOS_MemRegionsAdd(VOID *pool, const LosMemRegion * const multipleMemRegions)进行内存池合一:

如果pool为空,则合并到主内存堆m_aucSysMem0。

如果不为空,则初始化一个新的内存池,合并多内存区域为一个从堆。

结合上文示意图,加上注释,实现比较清晰,直接阅读下代码即可。

本文带领大家一起剖析了鸿蒙轻内核M核的动态内存如何支持多段非连续性内存,包含结构体、运作示意图、新增接口等等。感谢阅读,如有任何问题、建议,都可以留言评论,谢谢。

更多学习内容,请点击关注IoT物联网社区,添加华为云IoT小助手微信号(hwc-iot),获取更多资讯

点击关注,第一时间了解华为云新鲜技术~

继续阅读