更新时间:2021-07-08 GMT+08:00
分享

开发指导

使用场景

动态内存管理的主要工作是动态分配并管理用户申请到的内存区间。

动态内存管理主要用于用户需要使用大小不等的内存块的场景。当用户需要使用内存时,可以通过操作系统的动态内存申请函数索取指定大小的内存块,一旦使用完毕,通过动态内存释放函数归还所占用内存,使之可以重复使用。

功能

Huawei LiteOS系统中的动态内存管理模块为用户提供下面几种功能,接口详细信息可以查看API参考。

功能分类

接口名

描述

初始化和删除内存池

LOS_MemInit

初始化一块指定的动态内存池,大小为size

LOS_MemDeInit

删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效

申请、释放动态内存

LOS_MemAlloc

从指定动态内存池中申请size长度的内存

LOS_MemFree

释放已申请的内存

LOS_MemRealloc

按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块

LOS_MemAllocAlign

从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存

获取内存池信息

LOS_MemPoolSizeGet

获取指定动态内存池的总大小

LOS_MemTotalUsedGet

获取指定动态内存池的总使用量大小

LOS_MemInfoGet

获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小

LOS_MemPoolList

打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效

获取内存块信息

LOS_MemFreeBlksGet

获取指定内存池的空闲内存块数量

LOS_MemUsedBlksGet

获取指定内存池已使用的内存块数量

LOS_MemTaskIdGet

获取申请了指定内存块的任务ID

LOS_MemLastUsedGet

获取内存池最后一个已使用内存块的结束地址

LOS_MemNodeSizeCheck

获取指定内存块的总大小和可用大小,仅打开LOSCFG_BASE_MEM_NODE_SIZE_CHECK时有效

LOS_MemFreeNodeShow

打印指定内存池的空闲内存块的大小及数量

检查指定内存池的完整性

LOS_MemIntegrityCheck

对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效

设置、获取内存检查级别,仅打开LOSCFG_BASE_MEM_NODE_SIZE_CHECK时有效

LOS_MemCheckLevelSet

设置内存检查级别

LOS_MemCheckLevelGet

获取内存检查级别

为指定模块申请、释放动态内存,仅打开LOSCFG_MEM_MUL_MODULE时有效

LOS_MemMalloc

从指定动态内存池分配size长度的内存给指定模块,并纳入模块统计

LOS_MemMfree

释放已经申请的内存块,并纳入模块统计

LOS_MemMallocAlign

从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存给指定模块,并纳入模块统计

LOS_MemMrealloc

按size大小重新分配内存块给指定模块,并将原内存块内容拷贝到新内存块,同时纳入模块统计。如果新内存块申请成功,则释放原内存块

获取指定模块的内存使用量

LOS_MemMusedGet

获取指定模块的内存使用量,仅打开LOSCFG_MEM_MUL_MODULE时有效

  • 动态内存提供了内存调测功能,具体使用方法见内存调测方法
  • 对于bestfit_little算法,只支持多内存池机制内存合法性检查,不支持其他内存调测功能。
  • 上述接口中,通过宏开关控制的都是内存调测功能相关的接口。
  • 通过LOS_MemAllocAlign/LOS_MemMallocAlign申请的内存进行LOS_MemRealloc/LOS_MemMrealloc操作后,不能保障新的内存首地址保持对齐。
  • 对于bestfit_little算法,不支持对LOS_MemAllocAlign申请的内存进行LOS_MemRealloc操作,否则将返回失败。

开发流程

本节介绍使用动态内存的典型场景开发流程。

  1. 在los_config.h文件中配置项动态内存池起始地址与大小。

    配置项

    含义

    取值范围

    默认值

    依赖

    OS_SYS_MEM_ADDR

    系统动态内存起始地址

    [0, n)

    &m_aucSysMem1[0]

    OS_SYS_MEM_SIZE

    系统动态内存池的大小(DDR自适应配置),以byte为单位

    [0, n)

    从bss段末尾至系统DDR末尾

    • OS_SYS_MEM_ADDR:一般使用默认值即可。
    • OS_SYS_MEM_SIZE:一般使用默认值即可。
  2. 执行make menuconfig命令,进入Kernel ---> Memory Management菜单,完成动态内存管理模块的配置。

    配置项

    含义

    取值范围

    默认值

    依赖

    LOSCFG_KERNEL_MEM_BESTFIT

    选择bestfit内存管理算法

    YES/NO

    YES

    LOSCFG_KERNEL_MEM_BESTFIT_LITTLE

    选择bestfit_little内存管理算法

    YES/NO

    NO

    LOSCFG_KERNEL_MEM_SLAB_EXTENTION

    使能slab功能,可以降低系统持续运行过程中内存碎片化的程度

    YES/NO

    NO

    LOSCFG_KERNEL_MEM_SLAB_AUTO_EXPANSION_MODE

    slab自动扩展,当分配给slab的内存不足时,能够自动从系统内存池中申请新的空间进行扩展

    YES/NO

    NO

    LOSCFG_KERNEL_MEM_SLAB_EXTENTION

    LOSCFG_MEM_TASK_STAT

    使能任务内存统计

    YES/NO

    YES

    LOSCFG_KERNEL_MEM_BESTFIT或LOSCFG_KERNEL_MEM_BESTFIT_LITTLE

  3. 初始化LOS_MemInit。

    初始一个内存池后如图,生成一个 EndNode,并且剩余的内存全部被标记为FreeNode节点。注:EndNode作为内存池末尾的节点,size为0。

  4. 申请任意大小的动态内存LOS_MemAlloc。

    判断动态内存池中是否存在申请量大小的空间,若存在,则划出一块内存块,以指针形式返回,若不存在,返回NULL。

    调用三次LOS_MemAlloc函数可以创建三个节点,假设分别为UsedA,UsedB,UsedC,大小分别为sizeA,sizeB,sizeC。因为刚初始化内存池的时候只有一个大的FreeNode,所以这些内存块是从这个FreeNode中切割出来的。

    当内存池中存在多个FreeNode的时候进行malloc,将会适配最合适大小的FreeNode用来新建内存块,减少内存碎片。若新建的内存块不等于被使用的FreeNode的大小,则在新建内存块后,多余的内存又会被标记为一个新的FreeNode。

  5. 释放动态内存LOS_MemFree。

    回收内存块,供下一次使用。

    假设调用LOS_MemFree释放内存块UsedB,则会回收内存块UsedB,并且将其标记为FreeNode。在回收内存块时,相邻的FreeNode会自动合并。

平台差异性

无。

相关文档