[连载]嵌入式实时操作系统AIOS设计与实现 – 内存管理

来源:互联网 发布:华为光猫更改ssh端口 编辑:程序博客网 时间:2024/06/17 12:42
嵌入式实时操作系统一般都运行在资源非常有限的芯片上,对内存管理要求比较严格,若使用方式比较粗放,很可能导致内存紧张。在此,我们先提出对内存管理的几点要求,后面再按照这个要求逐步实现。有兴趣的朋友也可以一起思考,共同实现!


对内存管理的相关要求如下:
1、在嵌入式操作系统未使用之前,为其分配的为一块连续的内存空间;
2、该内存空间可以由用户自由指定,即内存的起始位置可以进行配置,方便应用开发,也便于对内存的安全管理;
3、在用户使用时,可以从连续的内存块中自由取出指定大小的内存区域,以供专门的使用,比如为系统任务、消息队列、信号量、互斥锁等分配内存空间;
4、在用户释放内存空间后(如任务生命期结束,释放该任务占用的内存空间),可以由系统进行回收。若出现内存碎片,则相邻的内存碎片可以合并成一个较大的内存区域,供下次内存分配使用;


内存管理永远是一个操作系统中比较核心的内容,即使考虑的再周到也难以避免内存碎片的问题。尤其是动态内存的频繁分配与释放,往往会导致某些“破碎”的内存不可再次使用,尤其是嵌入式实时操作系统,内存资源更加宝贵。因此,在使用时,我们尽量把内存使用方式静态化——内存专用,即分给某一任务、消息队列、信号量或者互斥锁等的内存尽量固定下来,避免对内存的频繁分配与释放;


内存管理具体实现方式如下:


为嵌入式实时操作系统分配的内存大小可由用户进行配置。

#define OSMEM_SIZEOSTOTAL_HEAP_SIZE

用户可以通过上面的宏定义变量OSTOTAL_HEAP_SIZE进行配置,为系统分配特定大小的内存空间。上面我们对此进行再次定义,主要目的是与用户的配置隔离开,以便内存管理相关的函数操作不受用户配置的影响。下面内存管理相关的操作变量均采用宏定义变量OSMEM_SIZE实现;


由于嵌入式实时操作系统内存资源比较宝贵,在进行设计的时候,我们需要进行“量体裁衣”,尽量避免资源浪费的情况出现;接下来我们根据用户分配的内存大小设置内存控制变量的类型;
#if OSMEM_SIZE > 64000Ltypedef uOS32_t uOSMemSize_t;#elsetypedef uOS16_t uOSMemSize_t;#endif

上述代码比较简单明了,若用户定义的内存长度超出64000,我们使用uOS32_t作为内存管理的变量类型,若长度小于64000,则使用uOS16_t作为内存管理的变量类型;细心的朋友可能发现了,uOS16_t的表示范围到65535了,这里怎么使用64000作为分界线呢?是的,因为内存管理自身的相关操作也需要占用内存,这句话读起来好像有点拗口啊。在内存管理时,我们为内存块设置了若干个信息记录表(表的数量与内存块的数量是一一对应的),信息记录表用于记录该内存块的使用情况,如该内存块的前一个相邻内存块位置,后一个相邻内存块位置,以及该内存块是否已经被分配使用等等;冗余的1535个位置即为内存块记录信息使用,若系统中分配的内存块较多,则会占用的较多,一般情况下,1535的大小足够内存信息记录表使用了;


下面我们为内存定义最小可分配的内存块大小,默认为12个字节长;
#ifndef MIN_SIZE#define MIN_SIZE             12#endif

定义此最小内存块大小的目的也是为了避免内存区出现琐碎的碎片,从而导致碎片不可再次回收利用;


在内存定义实现之前,我们再来看一个内存对齐的宏定义;
#ifndef OSMEM_ALIGN_SIZE#define OSMEM_ALIGN_SIZE(size) (((size) + OSMEM_ALIGNMENT - 1) & ~(OSMEM_ALIGNMENT-1))#endif

在STM32F1系列的芯片中,我们定义OSMEM_ALIGNMENT为4字节对齐方式;通过OSMEM_ALIGN_SIZE的宏定义,我们可以获取4字节的整数倍数值,例如,若指定size大小为13或者15,则返回数值为16;


内存表信息结构体定义如下;
typedef struct _tOSMem {  uOSMemSize_t NextMem;/*相邻的后一内存块地址 */  uOSMemSize_t PrevMem;/*相邻的前一内存块地址*/  uOS8_t used;/*内存块的使用标志1: 该内存块已使用; 0: 未使用*/}tOSMem_t;

对齐后的内存区块数值大小由如下宏定义实现:
#define SIZEOF_OSMEM_ALIGNEDOSMEM_ALIGN_SIZE(sizeof(tOSMem_t))#define OSMEM_SIZE_ALIGNEDOSMEM_ALIGN_SIZE(OSMEM_SIZE)


下面就是操作系统内存区域具体的实现方式了:
#ifndef OSRAM_HEAP_POINTERuOS8_t OSRamHeap[OSMEM_SIZE_ALIGNED + (2*SIZEOF_OSMEM_ALIGNED) + OSMEM_ALIGNMENT];#define OSRAM_HEAP_POINTER OSRamHeap#endif

上述OSRAM_HEAP_POINTER宏定义变量为系统所需的内存指针,该指针可由用户自行配置,指向具体的内存区。如若未配置,则通过数组的形式进行分配。
数组的长度=用户指定的长度+内存信息表的长度*2+内存对齐最小长度;
上述长度数值均是按照内存对齐方式处理过之后的长度数值;从上面的宏定义我们可以看出,若用户没有配置OSRAM_HEAP_POINTER的具体数值,系统则会把该变量指向数组OSRamHeap的首地址;


到现在,我们已经实现了上面提到的内存管理方面的第1和第2两项要求了,接着就是内存管理的具体实现方式了;

0 0
原创粉丝点击