
# 多模块内存统计
#### 使用场景
系统业务模块化清晰，用户需统计各模块的内存占用情况。
#### 功能说明
Huawei LiteOS提供了一套基于内核内存接口的封装接口，增加模块ID作为入参。不同业务模块进行内存操作时，调用对应封装接口，可统计各模块的内存使用情况，并通过模块ID获取指定模块的内存使用情况。
| 功能分类                   | 接口名                | 描述                                                     |
|:---|:---|:---|
| 为指定模块申请、释放动态内存，并纳入模块统计 | LOS_MemMalloc      | 从指定动态内存池分配size长度的内存给指定模块                               |
| 为指定模块申请、释放动态内存，并纳入模块统计 | LOS_MemMfree       | 释放指定模块的内存块                                             |
| 为指定模块申请、释放动态内存，并纳入模块统计 | LOS_MemMallocAlign | 从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存给指定模块             |
| 为指定模块申请、释放动态内存，并纳入模块统计 | LOS_MemMrealloc    | 按size大小重新分配内存块给指定模块，并将原内存块内容拷贝到新内存块。如果新内存块申请成功，则释放原内存块 |
| 获取指定模块的内存使用量           | LOS_MemMusedGet    | 获取指定模块的内存使用量，单位为Byte                                   |
   
#### 使用方法
1. 通过make menuconfig打开多模块内存统计功能。
   - 目前只有bestfit内存管理算法支持该功能，需要使能LOSCFG_KERNEL_MEM_BESTFIT：
     ```
     Kernel ---> Memory Management ---> Dynamic Memory Management Algorithm ---> bestfit
     ```
     
   
   - 该功能依赖于LOSCFG_MEM_MUL_MODULE，使用时需要在菜单项中开启"Enable Memory module statistics"：
     ```
     Debug  ---> Enable a Debug Version ---> Enable MEM Debug ---> Enable Memory module statistics
     ```
     
    
2. 每个业务模块配置唯一module ID，模块代码中在内存操作时调用对应接口，并传入相应模块ID。
3. 通过LOS_MemMusedGet接口获取指定模块的内存使用情况，可用于模块内存占用优化分析。
 
#### 注意事项
- 模块ID由宏MEM_MODULE_MAX限定，当系统模块个数超过该值时，需修改MEM_MODULE_MAX。
- 模块中所有内存操作都需调用封装接口，否则可能导致统计不准确。
- 目前只有bestfit内存管理算法支持该功能，需要使能LOSCFG_KERNEL_MEM_BESTFIT。
 
#### 编程实例
```
void test(void)
{
    void *ptr = NULL;
    void *ptrTmp = NULL;
    UINT32 size = 0x10;
    UINT32 module = 0;
    UINT32 memUsed = 0;
    ptr = LOS_MemMalloc(OS_SYS_MEM_ADDR, size, module);
    if (ptr == NULL) {
        PRINTK("module %d malloc failed\n", module);
    } else {
        PRINTK("module %d malloc successed\n", module);
    }
    memUsed = LOS_MemMusedGet(module);
    PRINTK("module %d mem used size %d\n", module, memUsed);
    module = 1;
    ptrTmp = LOS_MemMalloc(OS_SYS_MEM_ADDR, size, module);
    if (ptrTmp == NULL) {
        PRINTK("module %d malloc failed\n", module);
    } else {
        PRINTK("module %d malloc successed\n", module);
    }
    memUsed = LOS_MemMusedGet(module);
    PRINTK("module %d mem used size %d\n", module, memUsed);
    module = 0;
    LOS_MemMfree(OS_SYS_MEM_ADDR, ptr, module);
    module = 1;
    LOS_MemMfree(OS_SYS_MEM_ADDR, ptrTmp, module);
}
```
log：
```
module 0 malloc successed
module 0 mem used size 32
module 1 malloc successed
module 1 mem used size 32
```
