[优质文档]平板式内存治理
平板式内存管理
1+谢国经
1(广东海洋大学,,,,,电子信息工程1071班,湛江市,,,,,,,,,,524088)
Flat,,,,,memory,,,,,management
1+Xie,,,,,Guo,,,,,Jing
1(Department,,,,,of,,,,,,,,,,Electronic,,,,,Engineering,,,,,of,,,,,Guangdong,,,,,Ocean,,,,,University,,,,,,ZhanJiang,,,,,5240
00,,,,,,China
Abstract:
,,,,,Memory,,,,,management,,,,,There,,,,,are,,,,,many,,,,,ways,,,,,,of,,,,,this,,,,,paper,,,,,is,,,,,not,,,,,a,,,,,si *
mple,,,,,chip,,,,,MMU,,,,,memory,,,,,management.,,,,,This,,,,,planar,,,,,main,,,,,memory,,,,,management,,,,,system,,,,,
with,,,,,a,,,,,simple,,,,,multi-tasking.,,,,,Although,,,,,the,,,,,memory,,,,,management,,,,,there,,,,,are,,,,,a,,,,,lack,,,,,of,,,,,flexibility,,,,,,but,,,,,achieving,,,,,very,,,,,simple,,,,,,and,,,,,portability,,,,,is,,,,,very,,,,,strong.,,,,,Therefore,,,,,,there,,,,,is,,,,,no,,,,,memory,,,,,management,,,,,unit,,,,,MMU,,,,,chips,,,,,are,,,,,widely,,,,,used.,,,,,This,,,,,article,,,,,gives,,,,,concrete,,,,,realization,,,,,of,,,,,the,,,,,source,,,,,code.
Key,,,,,words: *,,,,,Memory,,,,,management;,,,,,operating,,,,,system
摘,,,,,,,,,,要: *内存管理的方法有很多种~本文论述的是没有MMU芯片上的一种简单的内存管理方式。这种平面式的内存管理方式主要用简单的多任务系统。这种内存管理方式虽然在灵活性上有欠缺~但实现十分简单~而且移植性非常的强。因此在没有内存管理单元MMU的芯片中得到广泛的应用。本文将给出具体实现的源代码。
关键词: *内存管理,操作系统,
1 为什么需要平板式的内存管理方式
内存管理是操作系统的重要组成部分,内存管理是否高效直接影响到任务运行的效率。但可惜的是内存管理的方式很多情况受到硬件的限制,一些高级芯片或系统有MMU硬件单元,可以容易的实现分段、分页的内存管理方式,可以跑多进程的操作系统,像我们的PC机就是一个很好的例子。
具有MMU的片上系统不少,但在很多场合并不需要那么高级的芯片。比如以ARM7为内核的很多芯片(如LPC213X)足可以做很多的嵌入式产品,不仅降低了开发成本,而且还使得开发难度降低,开发周期变短。在这样的实际需求下,针对没有MMU片上系统的平板式内存管理方式应运而生。
2 平板式内存管理方式基本思想
操作系统用一个链表管理着系统空闲的内存块。当任务向系统申请内存块的时候,任务就会调用相应的系统函数,并以要申请的内存块大小作为参数,系统函数会在这个空闲的内存链表中查找对应大小的内存块,如果成功的查找到对应大小的内块,函数就会返回这个内存块的地址,并把这个内存块从系统内存空闲链表中取下来。如果查找不到符合要求的内存块,函数就会返回空指针,表示申请不到内存块。再分细一点又可以分为两种方式,一种是分配内存块的大小由函数参数传过来,系统根据这个参数在链表中找;另外一种是同一个链表中的内存块大小是相等的,需要不同大小的内存块要在不同的链表中申请。下面分别对这两种方式做详细介绍。
2.1 任意大小分配方式
刚开始时系统空闲内存链表是一块很大块的内存 A
经过几次分配插入后内存变得大小不一 B
有的变成了无法再用的碎片 C
图1,,,,,任意大小分配方式
这种可以分配任意大小的内存管理方式,系统用一个指针指向这块很大的内存块,如果有任务需要向系统申请内存块的时候,就会在这块大的内存块中查找,如果查找不到对应大小的内存块就会尝试去把大块的内存块分成两块,然后取合适的那块返还给用户,剩下的放到空闲链表中,等待别的任务申请。
当任务把以前申请到的内存块归还给系统的时候,系统会尝试把这块内存和链表中某块空闲的内存块组成一块连续的内存块,如果不能合并就会把这块内存块当作一个独立的节点放到内存空闲链表中。
以上这样的分配和释放方式会很容易产生一个问题,系统在经过多次分配和释放内存后会形成很多细小的内存块,这样的内存块即不能组成连续的内存块,也不能满足任务的需要,因此会导致内存的泄漏。内存的泄漏使得本来已经捉襟见肘的内存资源变得更加的紧张了。
在图1中有A、B、C三个指针,他们指向系统空闲的内存块,实际上他们是同一个,只是在不同的时间他们的表现形态不一样。A表示在系统开始时,管理的内存块;B表示经过几次分配后的空闲内存链表;C就是经过很多次分配回收后的系统空闲内存示意图。
这样的内存管理方式,申请和回收都要经过很长时间的运算,而且运算时间不是常数,因此不适合硬实时的嵌入式系统。
这样的内存管理方式虽然比较灵活,但由于存在这样的问题,本文不给出这种内存管理方式的实现代码。下面介绍另外一种更加适合硬实时系统的平板式内存管理方式。
2.2 固定大小分配方式
NULL
空内存指针 闲
内
存
块
图2固定大小分配方式
固定大小分配方式,不仅实现起来容易,而且实时性十分的高。这样的内存管理是预先把一大块的内存分配成固定大小的内存块,然后把他们连接成一个链表。这样当任务向系统申请内存块的时候,任务要把这个空闲内存的头指针作为参数传给系统,系统就会在这个链表中查找一块内存块返回给用户,如果链表是空的就返回NULL表示申请失败。
当任务释放内存块的时候,就要确定两个参数,第一个是要归还系统内存块的首地址,第二个是内存空闲链表的首地址。这样看起来真的会有点抽象,在看完下面的代码后再回过头来看这个文字相信你会有更加深刻的理解。
3 平板式内存管理方式具体实现
固定大小分配方式主要用三个函数来实现,OSMemCreate()是把一大块内存分成固定大小的块,并把他们组成一个链表,返回头指针。OSMemApply()向系统申请一个内存块函数。OSMemRelease()释放申请到的内存块。下面分别给出具体实现。
3.1 切割内存块
void,,,,,,,,,,*OSMemCreate(void,,,,,*,,,,,Addr,uint32,,,,,NumCake,uint32,,,,,,,,,,CakeSize
)
{
int,,,,,i;
void,,,,,,,,,,**TempLink1;
uint8,,,,,,,,,,*TempLink2;
if(Addr,,,,,==,,,,,NULL),,,,,,,,,,return,,,,,,,,,,NULL;
if(NumCake,,,,,==,,,,,1),,,,,,,,,,return,,,,,,,,,,Addr;
TempLink1,,,,,=,,,,,(void**)Addr;//指向数组首地址
TempLink2,,,,,=,,,,,(uint8*)Addr,,,,,+,,,,,CakeSize;//移动CakeSize
for(,,,,,i,,,,,=,,,,,0;,,,,,i,,,,,<,,,,,NumCake,,,,,-,,,,,1,,,,,;,,,,,i++)
{
*TempLink1,,,,,=(void,,,,,*)TempLink2;//保存下一个内存块到前一个内存块开头
,,,,,TempLink1,,,,,=,,,,,(void**)TempLink2;//移动指针指向下一个内存块
TempLink2,,,,,=,,,,,TempLink2+,,,,,CakeSize;//移动CakeSize
}
*TempLink1,,,,,=,,,,,(void,,,,,*)0;
return,,,,,,,,,,Addr;
}
这个函数有三个参数,void,,,,,*,,,,,Addr是将要进行切割的内存块首地址,在执行这个函数后者块内存就会按照后面两个参数的要求切割成若干块。uint32,,,,,NumCake是链表中内存块的数量,执行函数后链表中将会有NumCake,,,,,块空闲内存块。uint32,,,,,,,,,,CakeSize,,,,,是每一块内存的大小。
3.2 申请内存块
void,,,,,*OSMemApply(void,,,,,*MemPtr)
{
void,,,,,*TempLink;
if(MemPtr,,,,,==,,,,,NULL),,,,,,,,,,,,,,,return,,,,,,,,,,NULL;//
TempLink,,,,,=,,,,,MemPtr;//获得第一块
MemPtr,,,,,=,,,,,*(void**)TempLink;//移动指针,从链表中删除已经申请了的内存块
return,,,,,,,,,,TempLink;
}
申请内存块实际上就是进行一个链表的删除操作。 3.3 释放内存块
int8,,,,,,,,,,,,,,,OSMemRelease(void,,,,,*MemPtr,void,,,,,*CakePtr)
{
*(void**)CakePtr,,,,,=,,,,,,,,,,MemPtr;
MemPtr,,,,,=,,,,,CakePtr;
return,,,,,OS_OK;
}
把内存块归还系统,时间上就是进行链表的一个插入操作。
4 应用
4.1 图文说明
在多任务系统中常常需要进行任务之间的通信,承载信息需要内存,因此在这样的情况下可以向系统申请一块内存,然后写入要发送的信息,并把这这块消息发送到别的任务,任务收到消息并处理完后就可以把这块内存块归还系统。等待别的任务使用。以上文字描述的过程用图来表达就是图3所示。
TASK2消息队
列
5、TASK2
2、处理完消4、取消息 3、向TASK2发送TASK1息后归还消息 把消息内存块
内容写
进内存承载块并发消息6、 送 1、申的内归还
请内存块 内存
存块 块
NULL
空闲空闲空闲空闲内存指针 内存内存内存内存
块 块 块 块
图3动态内存分配应用举例
4.2 代码实现
全局变量的定义:
#include,,,,,"config.h"
#define,,,,,,,,,,Message,,,,,,,,,,,,,,,22
OS_STK,,,,,,,,,,,,,,,UsrStk[3][100];//任务堆栈
void,,,,,*UsrMemPtr;//系统空闲内存块头指针 int,,,,,UsrMem[100][32];//系统总的内存块大小 OS_TASK,,,,,*UsrTaskPtr[2];//保存任务ID
消息处理函数:
void,,,,,UsrHandleMsg(void,,,,,*Msg)
{//处理消息函数
}
任务1,申请内存块并向任务2发送消息: void,,,,,TaskMem1(void*Pd)
{
int,,,,,*TaskMemPtr;//
while(1){
,,,,,,,,,,,,,,, if((TaskMemPtr,,,,,=,,,,,OSMemApply(UsrMemPtr)),,,,,!=,,,,,NULL){//申请内存块
,,,,,,,,,,,,,,, *TaskMemPtr,,,,,=,,,,,Message;//申请成功就写进要发送的消息
,,,,,,,,,,,,,,, OSTaskMsgPost(UsrTaskPtr[1],TaskMemPtr,,,,,,0);//发送消息到任务2
,,,,,,,,,,,,,,, }
,,,,,,,,,,,,,,, }
}
任务2,接收任务1发来的消息处理并释放内存块: void,,,,,TaskMem2(void*Pd)
{
int,,,,,*TaskMemPtr;//
while(1){
if((TaskMemPtr,,,,,=,,,,,,,,,,OSTaskMsgPend()),,,,,!=,,,,,NULL){//取任务1发送过来的消息
UsrHandleMsg(TaskMemPtr);//取到消息就处理消息 ,,,,,,,,,,,,,,, OSMemRelease(UsrMemPtr,TaskMemPtr);//归还内存块到系统 ,,,,,,,,,,,,,,, }
,,,,,,,,,,,,,,, }
}
主函数,启动系统并创建任务,创建空闲内存链表。 int,,,,,main,,,,,(void)
{,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,OSSystemInit();,,,,,//系统初始化 ,,,,,,,,,,,,,,,,,,,,,,,,,UsrMemPtr,,,,,=,,,,,OSMemCreate(UsrMem,100,32);//切割大块的内存为100块,每块为32
字节
,,,,,,,,,,,,,,,,,,,,,,,,, UsrTaskPtr[0],,,,,=,,,,,OSTaskCreate(TaskMem1,,,,,,NULL,,,,,,,,,,,&UsrStk[2][99],,,,,,2);//创
建任务1
,,,,,,,,,,,,,,,,,,,,,,,,, UsrTaskPtr[1],,,,,=,,,,,OSTaskCreate(TaskMem2,,,,,,NULL,,,,,,,,,,,&UsrStk[1][99],,,,,,2);//创
建任务2
,,,,,,,,,,,,,,,,,,,,,,,,, OSStart();//进入多任务环境
,,,,,,,,,,,,,,,,,,,,,,,,, while(1);,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,, return,,,,,0;
}
致谢,,,,,,,,,,*感谢王峰老师感谢王峰老师一直以来给我的细心指导;感谢宿舍的朋友们给了我安静的学习环
境。,,,,,
参考文献:
[1] 周立功等,,,,,,,,,,,,,,,,,,,,ARM微控制器基础与实践(第2版)2005年 [2] 周立功,,,,,张华,,,,,等,,,,,深入浅ARM7--LPC213x/LPC214x(上册)2005年 [3] [美]JeanJ.Labrosse,,,,,嵌入式实时操作系uC/OS—II(第2版)2003年
谢国经,,,,,(1987—)男,广东
中山人,本科,广东海洋大学信
息学院学生,主要研究基于
ARM的嵌入式实时操作系统