概述
基本概念
内存管理模块管理系统的内存资源,它是操作系统的核心模块之一,主要包括内存的初始化、分配以及释放。
在系统运行过程中,内存管理模块通过对内存的申请/释放来管理用户和OS对内存的使用,使内存的利用率和使用效率达到最优,同时最大限度地解决系统的内存碎片问题。
Huawei LiteOS的内存管理分为静态内存管理和动态内存管理,提供内存初始化、分配、释放等功能。
- 动态内存:在动态内存池中分配用户指定大小的内存块。
- 优点:按需分配。
- 缺点:内存池中可能出现碎片。
- 静态内存:在静态内存池中分配用户初始化时预设(固定)大小的内存块。
- 优点:分配和释放效率高,静态内存池中无碎片。
- 缺点:只能申请到初始化预设大小的内存块,不能按需申请。
动态内存运作机制
动态内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。
与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。
LiteOS动态内存支持bestfit(也称为dlink)和bestfit_little两种内存管理算法。
- bestfit。
bestfit内存管理结构如下图所示:
图1 bestfit动态内存管理结构图- 第一部分
- 第二部分
本身是一个数组,每个元素是一个双向链表,所有free节点的控制头都会被分类挂在这个数组的双向链表中。
假设内存允许的最小节点为2min字节,则数组的第一个双向链表存储的是所有size为2min<size< 2min+1的free节点,第二个双向链表存储的是所有size为2min+1<size< 2min+2的free节点,依次类推第n个双向链表存储的是所有size为2min+n-1<size< 2min+n的free节点。每次申请内存的时候,会从这个数组检索最合适大小的free节点以分配内存。每次释放内存时,会将该内存作为free节点存储至这个数组以便下次再使用。
- 第三部分
占用内存池极大部分的空间,是用于存放各节点的实际区域。以下是LosMemDynNode节点结构体申明以及简单介绍:
typedef struct { union { LOS_DL_LIST freeNodeInfo; /* Free memory node */ struct { UINT32 magic; UINT32 taskId : 16; }; }; struct tagLosMemDynNode *preNode; UINT32 sizeAndFlag; } LosMemCtlNode; typedef struct tagLosMemDynNode { LosMemCtlNode selfNode; } LosMemDynNode;
图2 LosMemDynNode结构体介绍图图3 对齐方式申请内存结果示意当申请到的节点包含的数据空间首地址不符合对齐要求时需要进行对齐,通过增加Gap域确保返回的指针符合对齐要求。
- bestfit_little。
bestfit_little算法是在最佳适配算法的基础上加入slab机制形成的算法。最佳适配算法使得每次分配内存时,都会选择内存池中最小最适合的内存块进行分配,而slab机制可以用于分配固定大小的内存块,从而减小产生内存碎片的可能性。
Huawei LiteOS内存管理中的slab机制支持配置slab class数目及每个class的最大空间。
现以内存池中共有4个slab class,每个slab class的最大空间为512字节为例说明slab机制。这4个slab class是从内存池中按照最佳适配算法分配出来的。第一个slab class被分为32个16字节的slab块,第二个slab class被分为16个32字节的slab块,第三个slab class被分为8个64字节的slab块,第四个slab class被分为4个128字节的slab块。
初始化内存模块时,首先初始化内存池,然后在初始化后的内存池中按照最佳适配算法申请4个slab class,再逐个按照slab内存管理机制初始化4个slab class。
每次申请内存时,先在满足申请大小的最佳slab class中申请(比如用户申请20字节内存,就在slab块大小为32字节的slab class中申请),如果申请成功,就将slab内存块整块返回给用户,释放时整块回收。需要注意的是,如果满足条件的slab class中已无可以分配的内存块,则从内存池中按照最佳适配算法申请,而不会继续从有着更大slab块空间的slab class中申请。释放内存时,先检查释放的内存块是否属于slab class,如果是则还回对应的slab class中,否则还回内存池中。
静态内存运作机制
静态内存实质上是一个静态数组,静态内存池内的块大小在初始化时设定,初始化后块大小不可变更。
静态内存池由一个控制块和若干相同大小的内存块构成。控制块位于内存池头部,用于内存块管理。内存块的申请和释放以块大小为粒度。