ucos linux 内存管理,uc/os-ii操作系统的内存管理实现实例--很受用!

每次 温故uc/os-ii操作系统的源码都有收获,经典的东西就是经典;uc/os-ii曾经把我搞得好累,但是经过一段时间摸索之后发现只要有正确的学习方法,学好uc/os-ii并不难,同时基于uc/os-ii操作系统的应用程序开发也不难。关于嵌入式系统内存管理的方法应该不少,原子的内存管理教程就有两个例程,一个是“特大号数组”型,一个是动态分配型,两者都使用了malloc()函数。而uc/os-ii操作系统的内存管理实现原理很精妙没有使用malloc()函数,主要是考虑该函数申请内存的时间不确定性。可以说,通过该例程就能理解uc/os-ii操作系统的内存管理实现原理。笔者认为通过实例学习,理解uc/os-ii操作系统的原理是个不错的选择。本实验基于PC机在DOS环境下模拟。

/*设计一个有3个任务的应用程序,这3个任务分别是Mytask Youtask Hertask。在应用程序中创建一个动态内存分区,该分区有8个内存块,每个内存块的长度是6字节。应用程序的任务Youtask Hertask都在任务运行后请求一个内存块.随后就释放它;任务MYTASK也在任务运行后请求一个内存块,但是要在任务MYTASK运行6次后,才释放它所申请的内存块。为了了解内存分区变化的情况,编写代码来观察分区头指针和已被使用内存块的个数*/

#include "INCLUDES.h"

#define  TASK_STK_SIZE        512       /* 任务堆栈长度*/

OS_STK        StartTaskStk[TASK_STK_SIZE];    /*定义任务堆栈区 */

OS_STK        MyTaskStk[TASK_STK_SIZE];

OS_STK        YouTaskStk[TASK_STK_SIZE];

OS_STK        HerTaskStk[TASK_STK_SIZE];

char *s;

char *s1= "Mytask  ";

char *s2= "Youtask ";

char *s3= "Hertask ";

INT8U  err;

INT8U  y=0;   //字符显示位置

INT8U  Times=0;

OS_MEM        *IntBuffer;      /*定义内存控制块指针,创建一个内存分区时,返回值就是它 */

INT8U         IntPart[8][6];  /*划分一个具有8个内存块,每个内存块长度是6的内存分区 */

INT8U         *IntBlkPtr;      /*定义内存块指针,确定内存分区中首个内存块的指针  */

OS_MEM_DATA MemInfo;   /*存放内存分区的状态信息 */

void  StartTask(void *data);               /* 声明起始任务  */

void  MyTask(void *data);                  /* 声明任务      */

void  YouTask(void *data);                 /* 声明任务      */

void  HerTask(void *data);                 /* 声明任务      */

/*

********************************************************************

*              MAIN主函数

**********************************************************************

*/

void  main (void)

{

OSInit();               /* 初始化uC/OS-II                      */

PC_DOSSaveReturn();       /* 保存DOS环境     */

PC_VectSet(uCOS, OSCtxSw);     /* 安装uC/OS-II的中断 */

IntBuffer=OSMemCreate(IntPart,8,6,&err);    /*创建动态内存区  */

OSTaskCreate(StartTask, (void *)0, &StartTaskStk[TASK_STK_SIZE - 1], 0);

OSStart();             /* 启动多任务管理   */

}

/*

***********************************************************

*                STARTUP TASK:主要功能就是创建3个任务

***********************************************************

*/

void  StartTask(void *pdata)

{

#if OS_CRITICAL_METHOD == 3      /* Allocate storage for CPU status register,实际应用中该部分可省略 */

OS_CPU_SR  cpu_sr;

#endif

INT16S        key;          /*用于退出的建*/

pdata = pdata;          /* Prevent compiler warning                 */

OS_ENTER_CRITICAL();

PC_VectSet(0x08, OSTickISR);      /* 安装时钟中断向量 , */

PC_SetTickRate(OS_TICKS_PER_SEC);   /* 设置时钟频率 */

OS_EXIT_CRITICAL();

OSStatInit();        /* 初始化统计任务   */

OSTaskCreate(MyTask, (void *)0, &MyTaskStk[TASK_STK_SIZE - 1], 3);

OSTaskCreate(YouTask, (void *)0, &YouTaskStk[TASK_STK_SIZE - 1], 4);

OSTaskCreate(HerTask, (void *)0, &HerTaskStk[TASK_STK_SIZE - 1], 5);

for (;;) {

//如果恩下ESC键,则退出UC/OS-II

if (PC_GetKey(&key) == TRUE) {   /* See if key has been pressed     */

if (key == 0x1B) {       /* Yes, see if it's the ESCAPE key    */

PC_DOSReturn();    /* Return to DOS       */

}

}

OSTimeDlyHMSM(0, 0, 3, 0);   /* Wait 3s,在这里创建完StartTask任务为什么不挂起自己?      */

}

}

/*--------------------MyTask任务-------------------------*/

void MyTask(void *pdata)

{

#if OS_CRITICAL_METHOD == 3       /* Allocate storage for CPU status register */

OS_CPU_SR  cpu_sr;

#endif

pdata=pdata;

for( ; ; )

{

PC_DispStr(10,++y,s1,DISP_BGND_BLACK+DISP_FGND_WHITE);  /*"++y"执行一次就换一次行  */

IntBlkPtr=OSMemGet(   /*请求内存分区的内存块的指针 */

IntBuffer, /*这个参数就指明了要获取的内存块属于哪个内存分区 */

&err);

OSMemQuery(        /*查询内存控制块信息 */

IntBuffer,     /*带查询内存控制块指针 */

&MemInfo);

sprintf(s,"%0x",MemInfo.OSFreeList);  /*显示头指针 */

PC_DispStr(30,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);

sprintf(s,"%d",MemInfo.OSNUsed);  /*显示已用的内存块数目 */

PC_DispStr(40,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);

if(Times>4)  /*0-1-2-3-4-5;Times==6时该条件语句为真 */

{

OSMemPut(IntBuffer,IntBlkPtr);   /* 进入第6次就释放已经使用过的内存块  */

}

Times++;

OSTimeDlyHMSM(0,0,1,0);  //等待2s

}

}

/*-------------------------------Youtask-------------------------------------*/

void YouTask(void *pdata)

{

#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */

OS_CPU_SR  cpu_sr;

#endif

pdata=pdata;

for( ; ; )

{

PC_DispStr(10,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE);

IntBlkPtr=OSMemGet(            //请求内存块

IntBuffer,   //内存分区的指针

&err);       //错误信息

OSMemQuery(        //查询内存控制块信息

IntBuffer,     //带查询内存控制块指针

&MemInfo);

sprintf(s,"%0x",MemInfo.OSFreeList);  //显示头指针

PC_DispStr(30,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);

sprintf(s,"%d",MemInfo.OSNUsed);  //显示已用的内存块数目

PC_DispStr(40,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);

OSMemPut( IntBuffer, IntBlkPtr );

OSTimeDlyHMSM(0,0,2,0);  //等待2s

}

}

/*-------------------------------Hertask-------------------------------------*/

void HerTask(void *pdata)

{

#if OS_CRITICAL_METHOD == 3      /* Allocate storage for CPU status register */

OS_CPU_SR  cpu_sr;

#endif

pdata=pdata;

for( ; ; )

{

PC_DispStr(10,++y,s3,DISP_BGND_BLACK+DISP_FGND_WHITE);

IntBlkPtr=OSMemGet(            //请求内存块

IntBuffer,   //内存分区的指针

&err);       //错误信息

OSMemQuery(        //查询内存控制块信息

IntBuffer,     //带查询内存控制块指针

&MemInfo);

sprintf(s,"%0x",MemInfo.OSFreeList);  //显示头指针

PC_DispStr(30,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);

sprintf(s,"%d",MemInfo.OSNUsed);  //显示已用的内存块数目

PC_DispStr(40,y,s,DISP_BGND_BLACK+DISP_FGND_WHITE);

OSMemPut(

IntBuffer,

IntBlkPtr

);

OSTimeDlyHMSM(0,0,1,0);  //等待2s

}

}

/*

通过本例的实验现象能深刻理解内存管理函数的本质;现象分析如下:

y(行)    显示内容:       显示头指针OSFreeList:     显示已用的内存块数目OSNUsed:

1,        MyTask              504                         1

2,        YouTask             50A                         2

3,        HerTask             50A                         2

4,        MyTask              50A                         2

5,        HerTask             510                         3

6,        MyTask              510                         3

7,        YouTask             516                         4

8,        HerTask             516                         4

9,        MyTask              516                         4

10,       HerTask             51C                         5

11,       MyTask              51C                         5

12,       YouTask             522                         6

13,       HerTask             522                         6

14,       MyTask              522                         6

15,       MyTask              522                         6

通过上表可以看出:1,“显示头指针OSFreeList”的数据很有规律,即都是以6为单位递增,这是因为在创建内存控制块时就定义了每个内存块的长度是6个字节,所以就是以6为单位递增,(0x504+0x6)==0x50A;

(0x50A+0x6)==0x510,(0x510+0x6)==0x516,等等; 2,第2行中,因为YouTask任务请求一个内存块之后就立即释放了,所以在第3个任务(HerTask任务)中,HerTask任务申请到的还是50A指针指向的内存块,同样在本任务中及时释放了内存块,实际上此时系统只占用504内存块,所以到第4个任务MyTask 任务执行时,还是显示已用2个内存块,不过这时MyTask 任务已经占用了两个内存块,因为此时MyTask 任务还没有释放内存块;3,当if(Times>4) 时 (0-1-2-3-4-5;Times==6时该条件语句为真)MyTask 任务得到一个内存块就立即释放了该内存块,所以就一直会显示已用6个内存块,指针值停留在0x522处,不会再递增了;4,由此现象得知:a),本例中申请到的8个内存块是连续的地址空间;b),系统在初始化时,就初始化了一个空的任务控制块链表,每个任务控制块的有效数据为空,但是结点指针都有所指;当系统申请一个内存分区时,空闲任务控制块就会减1,释放了就加1;c),整个空闲链表是不是一个大的连续内存空间,还不知道,我觉得应该看OSInit()源码。

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值