
# 开发指导
#### 使用场景
动态内存管理的主要工作是动态分配并管理用户申请到的内存区间。
动态内存管理主要用于用户需要使用大小不等的内存块的场景。当用户需要使用内存时，可以通过操作系统的动态内存申请函数索取指定大小的内存块，一旦使用完毕，通过动态内存释放函数归还所占用内存，使之可以重复使用。
#### 功能
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  | 设置内存检查级别                                                                                                 |
| 设置、获取内存检查级别，仅打开LOSCFG_BASE_MEM_NODE_SIZE_CHECK时有效 | LOS_MemCheckLevelGet  | 获取内存检查级别                                                                                                 |
| 为指定模块申请、释放动态内存，仅打开LOSCFG_MEM_MUL_MODULE时有效        | LOS_MemMalloc         | 从指定动态内存池分配size长度的内存给指定模块，并纳入模块统计                                                                         |
| 为指定模块申请、释放动态内存，仅打开LOSCFG_MEM_MUL_MODULE时有效        | LOS_MemMfree          | 释放已经申请的内存块，并纳入模块统计                                                                                       |
| 为指定模块申请、释放动态内存，仅打开LOSCFG_MEM_MUL_MODULE时有效        | LOS_MemMallocAlign    | 从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存给指定模块，并纳入模块统计                                                       |
| 为指定模块申请、释放动态内存，仅打开LOSCFG_MEM_MUL_MODULE时有效        | LOS_MemMrealloc       | 按size大小重新分配内存块给指定模块，并将原内存块内容拷贝到新内存块，同时纳入模块统计。如果新内存块申请成功，则释放原内存块                                          |
| 获取指定模块的内存使用量                                      | LOS_MemMusedGet       | 获取指定模块的内存使用量，仅打开LOSCFG_MEM_MUL_MODULE时有效                                                                 |
   
![](https://support.huaweicloud.com/kernelmanual-LiteOS/public_sys-resources/notice_3.0-zh-cn.png)
- 动态内存提供了内存调测功能，具体使用方法见[内存调测方法](https://support.huaweicloud.com/maintenance-LiteOS/zh-cn_topic_0312244434.html)。
- 对于bestfit_little算法，只支持[多内存池机制](https://support.huaweicloud.com/maintenance-LiteOS/zh-cn_topic_0312244436.html)和[内存合法性检查](https://support.huaweicloud.com/maintenance-LiteOS/zh-cn_topic_0312244438.html)，不支持其他内存调测功能。
- 上述接口中，通过宏开关控制的都是内存调测功能相关的接口。
- 通过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。
   ![](https://support.huaweicloud.com/kernelmanual-LiteOS/zh-cn_image_0175230266.jpg "点击放大")
   
4. 申请任意大小的动态内存LOS_MemAlloc。 判断动态内存池中是否存在申请量大小的空间，若存在，则划出一块内存块，以指针形式返回，若不存在，返回NULL。
   调用三次LOS_MemAlloc函数可以创建三个节点，假设分别为UsedA，UsedB，UsedC，大小分别为sizeA，sizeB，sizeC。因为刚初始化内存池的时候只有一个大的FreeNode，所以这些内存块是从这个FreeNode中切割出来的。
   ![](https://support.huaweicloud.com/kernelmanual-LiteOS/zh-cn_image_0175230636.jpg "点击放大")
   当内存池中存在多个FreeNode的时候进行malloc，将会适配最合适大小的FreeNode用来新建内存块，减少内存碎片。若新建的内存块不等于被使用的FreeNode的大小，则在新建内存块后，多余的内存又会被标记为一个新的FreeNode。
   
5. 释放动态内存LOS_MemFree。 回收内存块，供下一次使用。
   假设调用LOS_MemFree释放内存块UsedB，则会回收内存块UsedB，并且将其标记为FreeNode。在回收内存块时，相邻的FreeNode会自动合并。
   ![](https://support.huaweicloud.com/kernelmanual-LiteOS/zh-cn_image_0175230495.jpg "点击放大")
   
 
#### 平台差异性
无。
