1. 概述

1.1 基本概念

内存管理模块管理系统的内存资源,它是操作系统的核心模块之一。主要包括内存的初始化、分配以及释放。

在系统运行过程中,内存管理模块通过对内存的申请/释放操作,来管理用户和OS对内存的使用,使内存的利用率和使用效率达到最优,同时最大限度地解决系统的内存碎片问题。

Huawei LiteOS的内存管理分为静态内存管理和动态内存管理,提供内存初始化、分配、释放等功能。

  • 动态内存:在动态内存池中分配用户指定大小的内存块。

    • 优点:按需分配。
    • 缺点:内存池中可能出现碎片。
  • 静态内存:在静态内存池中分配用户初始化时预设(固定)大小的内存块。
    • 优点:分配和释放效率高,静态内存池中无碎片。
    • 缺点:只能申请到初始化预设大小的内存块,不能按需申请。

1.2 动态内存运作机制

动态内存管理,即在内存资源充足的情况下,从系统配置的一块比较大的连续内存(内存池),根据用户需求,分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。

与静态内存相比,动态内存管理的好处是按需分配,缺点是内存池中容易出现碎片。

系统动态内存管理结构如图1所示:

第一部分:堆内存(也称内存池)的起始地址及堆区域总大小

第二部分:本身是一个数组,每个元素是一个双向链表,所有free节点的控制头都会被分类挂在这个数组的双向链表中。

假设内存允许的最小节点为2min字节,则数组的第一个双向链表存储的是所有size为2min<size< 2min+1的free节点,第二个双向链表存储的是所有size为2min+1<size< 2min+2的free节点,依次类推第n个双向链表存储的是所有size为2min+n-1<size< 2^min+n的free节点。(这个有点像buddy算法)每次申请内存的时候,会从这个数组检索最合适大小的free节点,进行分配内存。每次释放内存时,会将该片内存作为free节点存储至这个数组,以便下次再利用。

第三部分:占用内存池极大部分的空间,是用于存放各节点的实际区域。以下是LOS_MEM_DYN_NODE节点结构体申明以及简单介绍:

typedef struct tag LOS_MEM_DYN_NODE
{
LOS_DL_LIST stFreeNodeInfo;
struct tagLOS_MEM_DYN_NODE *pstPreNode;
UINT32 uwSizeAndFlag;
}LOS_MEM_DYN_NODE;

1.3 静态内存运作机制

静态内存实质上是一块静态数组,静态内存池内的块大小在初始化时设定,初始化后块大小不可变更。

静态内存池由一个控制块和若干相同大小的内存块构成。控制块位于内存池头部,用于内存块管理。内存块的申请和释放以块大小为粒度。

图 3-4 静态内存示意图

2. 动态内存

2.1 开发指导

2.1.1 使用场景

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

动态内存管理主要是在用户需要使用大小不等的内存块的场景中使用。

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

2.1.2 功能

Huawei LiteOS系统中的动态内存管理模块为用户提供下面几种功能,具体的API详见接口手册。

功能分类 接口名 描述
内存初始化 LOS_MemInit 初始化一块指定的动态内存池,大小为size。
申请动态内存 LOS_MemAlloc 从指定动态内存池中申请size长度的内存。
释放动态内存 LOS_MemFree 释放已申请的内存。
重新申请内存 LOS_MemRealloc 按size大小重新分配内存块,并保留原内存块内容。
内存对齐分配 LOS_MemAllocAlign 从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存。
获取内存大小 LOS_MemPoolSizeGet 获取指定的动态内存池总大小
获取内存大小 LOS_MemTotalUsedGet 获取指定动态内存池的总使用量大小
获取内存块数量 LOS_MemFreeBlksGet 获取指定内存池的空闲内存块数量
获取内存块数量 LOS_MemUsedBlksGet 获取指定内存池的已使用的内存块数量
获取分配指定内存区域的任务ID LOS_MemTaskIdGet 获取分配了指定内存区域的任务ID
获取最后节点内存大小 LOS_MemLastNodeGet 获取除大小为零的终端节点之外的最后一个节点的内存大小
获取内存结构信息 LOS_MemInfoGet 获取指定内存池的内存结构信息
对指定内存池做完整性检查 LOS_MemIntegrityCheck 对指定内存池做完整性检查
获取节点大小 LOS_MemNodeSizeCheck 获取节点的总大小和可操作大小
设定内存检查级别 LOS_MemCheckLevelSet 设定内存检查级别
获取内存检查级别 LOS_MemCheckLevelGet 获取内存检查级别

2.1.3 开发流程

  1. 配置:
  • OS_SYS_MEM_ADDR:系统动态内存池起始地址,一般不需要修改
  • OS_SYS_MEM_SIZE:系统动态内存池大小,以byte为单位,系统默认分配DDR后未使用的空间
  • LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK:内存越界检测开关,默认关闭。打开后,每次申请动态内存时执行动态内存块越界检查;每次释放静态内存时执行静态内存块越界检查。
  1. 初始化LOS_MemInit。

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

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

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

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

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

  1. 释放动态内存LOS_MemFree。

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

假设调用LOS_MemFree释放内存块UsedB,则会回收内存块UsedB,并且将其标记为FreeNode

2.1.4 平台差异性

2.2 编程实例

2.2.1 实例描述

Huawei LiteOS运行期间,用户需要频繁的使用内存资源,而内存资源有限,必须确保将有限的内存资源分配给急需的程序,同时释放不用的内存。

通过Huawei LiteOS内存管理模块可以保证高效、正确的申请、释放内存。

本实例执行以下步骤:

  1. 初始化一个动态内存池。
  2. 在动态内存池中申请一个内存块。
  3. 使用这块内存块存放一个数据。
  4. 打印出存放在内存块中的数据。
  5. 释放掉这块内存。

2.2.2 编程实例

VOID los_memory_test() {
UINT32 *p_num = NULL;
UINT32 uwRet;
uwRet = LOS_MemInit(m_aucSysMem0, 32);
if (LOS_OK == uwRet) {
dprintf("内存池初始化成功!\n");
}
else {
dprintf("内存池初始化失败!\n");
return;
}
/*分配内存*/
p_num = (int*)LOS_MemAlloc(m_aucSysMem0, 4);
if (NULL == p_num) {
dprintf("内存分配失败!\n");
return;
}
dprintf("内存分配成功\n");
/*赋值*/
*p_num = 828;
dprintf("*p_num = %d\n", *p_num);
/*释放内存*/
uwRet = LOS_MemFree(m_aucSysMem0, p_num);
if (LOS_OK == uwRet) {
dprintf("内存释放成功!\n");
}
else {
dprintf("内存释放失败!\n");
}
return;
}

2.2.3 结果验证

图 3-5 结果显示

3. 静态内存

3.1 开发指导

当用户需要使用固定长度的内存时,可以使用静态内存分配的方式获取内存,一旦使用完毕,通过静态内存释放函数归还所占用内存,使之可以重复使用。

3.2 功能

Huawei LiteOS的静态内存管理主要为用户提供以下功能。

功能分类 接口名 描述
初始化静态内存 LOS_MemboxInit 初始化一个静态内存池,设定其起始地址、总大小及每个块大小
清除静态内存内容 LOS_MemboxClr 清零静态内存块
申请一块静态内存 LOS_MemboxAlloc 申请一块静态内存块
释放内存 LOS_MemboxFree 释放一个静态内存块

3.3 开发流程

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

  1. 规划一片内存区域作为静态内存池。
  2. 调用LOS_MemboxInit接口。

系统内部将会初始化静态内存池。将入参指定的内存区域分割为N块(N值取决于

静态内存总大小和块大小),将所有内存块挂到空闲链表,在内存起始处放置控

制头。

  1. 调用LOS_MemboxAlloc接口。

系统内部将会从空闲链表中获取第一个空闲块,并返回该块的用户空间地址。

  1. 调用LOS_MemboxFree接口。

将该块内存加入空闲块链表。

  1. 调用LOS_MemboxClr接口。

系统内部清零静态内存块,将入参地址对应的内存块清零

3.3 编程实例

Huawei LiteOS运行期间,用户需要频繁的使用内存资源,而内存资源有限,必须确保将有限的内存资源分配给急需的程序,同时释放不用的内存。

通过内存管理模块可以保证正确且高效的申请释放内存。

本实例执行以下步骤:

  1. 初始化一个静态内存池。
  2. 从静态内存池中申请一块静态内存。
  3. 使用这块内存块存放一个数据。
  4. 打印出存放在内存块中的数据。
  5. 清除内存块中的数据。
  6. 释放掉这块内存;
VOID los_membox_test(void) {
UINT32 *p_num = NULL;
UINT32 uwBlkSize = 10, uwBoxSize = 100;
UINT32 uwRet;
UINT32 pBoxMem[1000];
uwRet = LOS_MemboxInit(&pBoxMem[0], uwBoxSize, uwBlkSize);
if (uwRet != LOS_OK)
{
dprintf("内存池初始化失败!\n");
return;
}
else {
dprintf("内存池初始化成功!\n");
}
/*申请内存块*/
p_num = (int*)LOS_MemboxAlloc(pBoxMem);
if (NULL == p_num) {
dprintf("内存分配失败!\n");
return;
}
dprintf("内存分配成功\n");
/*赋值*/
*p_num = 828;
dprintf("*p_num = %d\n", *p_num);
/*清除内存内容*/
LOS_MemboxClr(pBoxMem, p_num);
dprintf("清除内存内容成功\n *p_num = %d\n", *p_num);
/*释放内存*/
uwRet = LOS_MemboxFree(pBoxMem, p_num);
if (LOS_OK == uwRet) {
dprintf("内存释放成功!\n");
}
else{
dprintf("内存释放失败!\n");
}
return;

3.4 结果验证

图 3-6 结果显示

liteos内存(三)的更多相关文章

  1. IBM内存三技术:Chipkill、MPX、MM

    转自:解析IBM内存三技术:Chipkill.MPX.MM 内存作为服务器中的又一个重要的组成部分,对于企业的应用起着十分重要的作用.如今,企业用户对于服务器的要求逐渐提升,使得在提高内存密度.增大内 ...

  2. Android内存管理(11)*常见JVM回收机制「Java进程内存堆分代,JVM分代回收内存,三种垃圾回收器」

    参考: http://www.blogjava.net/rosen/archive/2010/05/21/321575.html 1,Java进程内存堆分代: 典型的JVM根据generation(代 ...

  3. Linux C申请内存三种基本方式

    一份代码可以知道具体方式和原理: int main() { int stack_a; int stack_b; static int static_c; static int static_d; in ...

  4. 【LiteOS】STM32F103-LiteOS移植教程(详细篇)【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  5. 【LiteOS】STM32F103-LiteOS移植教程(详细篇)

    总览 本文基于STM32F103C8T6,详细讲述华为LiteOS的移植过程.开发工具是MDK5.LiteOS官方已经适配过cortex M系列内核的单片机,因此移植过程非常简单. LiteOS有两种 ...

  6. 《深入浅出Node.js》第5章 内存控制(未完)

    @by Ruth92(转载请注明出处) 第5章 内存控制 基于无阻塞.事件驱动建立的 Node 服务,具有内存消耗低的优点,非常适合处理海量的网络请求. 内存控制正是在海量请求和长时间运行的前提下进行 ...

  7. IO端口和IO内存的区别 转

      目录(?)[-] Linux系统对IO端口和IO内存的管理 一.I/O端口 二.IO内存 三.IO端口和IO内存的区分及联系 四.外设IO端口物理地址的编址方式 统一编址 独立编址 优缺点 五.L ...

  8. Android 性能优化之使用MAT分析内存泄露问题

    我们平常在开发Android应用程序的时候,稍有不慎就有可能产生OOM,虽然JAVA有垃圾回收机,但也不能杜绝内存泄露,内存溢出等问题,随着科技的进步,移动设备的内存也越来越大了,但由于Android ...

  9. Java内存数据模型

    本篇文章带来的是对Java内存数据模型的介绍,这对于我们深入理解Jvm虚拟机工作的原理和Java内存的划分大有裨益,好了,为了让我们理解的更为深刻,我们将会加入图片辅助的方法去理解. 本篇博文的目录: ...

随机推荐

  1. BUPT 2012复试机考 2T

    题目描述 ​给你一个n*n的矩阵, , 求其矩阵的k次幂,即Pk 输入格式 第一行,一个整数T(0<T<=10),表示要求矩阵的个数. 接下来有T组数据,每组数据格式如下: 第一行:两个数 ...

  2. IOS UIPickView+sqlite 选择中国全部城市案例

    1.案例简单介绍 通过读取文件.将中国全部城市写入sqlite数据库中,现通过UIPickView实现中国全部城市的选择,效果图例如以下所看到的 2.城市对象模型 中国全部城市数据请看http://b ...

  3. POJ 3928 Ping pong 树状数组模板题

    開始用瓜神说的方法撸了一发线段树.早上没事闲的看了一下树状数组的方法,于是又写了一发树状数组 树状数组: #include <cstdio> #include <cstring> ...

  4. Linux内存管理之mmap详解 (可用于android底层内存调试)

    注:将android底层malloc换为mmap来获取内存,可将获取到的内存添加tag,从而再利用meminfo进行分析,可单独查看该tag的内存,从而进行分析. 一. mmap系统调用 1. mma ...

  5. [Other]来做一个微信打印机吧 -- 微信打印的设计思路參考

    项目源代码地址:https://github.com/callmewhy/why-wechat-printer 近期微信打印机小火了一把.比方印美团.747微信打印机,都是利用微信公共平台实现照片的打 ...

  6. MapReduce简述、工作流程及新旧API对照

    什么是MapReduce? 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查而且数出有多少张是黑桃. MapReduce方法则是: 1. 给在座的全部玩家中分配这摞牌. 2. 让每一个玩家数自己手 ...

  7. 通达OA二次开发 工作流表单中关联查询另外一个工作流方法(源代码)

    一个工作流表单中,怎样方便的查询相关的工作流表单内容.重复打开各个菜单必定须要造成多次点击浪费时间,切换也会带来思路的中断.这里通过js代码的方式把这个问题进行了解决. <style>&l ...

  8. spring中PropertyPlaceholderHelper替换占位符的值

    1.Properties中的值替换¥{}或者#{}占位符 String text = "foo=${foo},bar=${bar}"; Properties props = new ...

  9. POJ3281 Dining —— 最大流 + 拆点

    题目链接:https://vjudge.net/problem/POJ-3281 Dining Time Limit: 2000MS   Memory Limit: 65536K Total Subm ...

  10. HDU 5178 pairs —— 思维 + 二分

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5178 pairs Time Limit: 2000/1000 MS (Java/Others)     ...