ucos内存管理

来源:互联网 发布:好用的飞机杯 知乎 编辑:程序博客网 时间:2024/04/29 17:53

为了消除碎片,ucosii连续的打开内存按分区来管理,每个分区包含有整数个大小相同的内存块

类似每个人物对应一个人物块,每个时间对应一个事件块,ucosii每个内存块也是对应一个内存块,内存控制块是一个暑假结构

typedef struct{

   void *OSMemAddr;

   void *OSMemFreeList;

   INT32U OSMemBlkSize;

   INT32U OSMemNBlks;

  INT32U  OSMemNFree;

}OS_MEM;


OSMemAddr 是指向内存分区起始地址的指针,它在建立内存分区OSMemCreate时被初始化,在此之后就不能更改

OSMemFreeList 是指向下一个内存空闲内存控制块或下一个空闲的内存的指针,具体含义要根据gia内存分区是否已经建立来决定

OSMemBlkSize 是内存分区中内存块的大小,是用户建立该内存分区时指定的

OSMemNFree是内存分区中当前可以得空闲内存块数量


完整地使用内存,需要经过以下步骤:

1.建立一个内存分区(OSMemCreate())

2.调用OSMemGet函数从已经建立的内存分区中申请内存卡

3.当用户应用程序步子啊使用一个内存块是,调用OSMemPut释放内存

4.在这过程中可以调用OSMemQuery查询一个内存分区状态。


建立一个内存分区需要使用ucosii系统函数OSMemCreate()实现过程如下:


OS_MEM *OSMemCreate(void *addr,INT32U nblks,INT32U blksize,INT8U *err)

{

    OS_MEM *pmem;

    INT8U *pblk;

    void **plink;

    INT32U i;

    if(nblks<2)

   {

      *err=OS_MEM_INVALID_BLKS;

   }

  if(blksize<sizeof(void *))

 {

     *err=OS_MEM_INVALID_SIZE;

      return((OS_MEM*)0);

  }

OS_ENTER_CRITICAL();

pmem=OSMemFreeList;


if(OSMemFreeList!=(OS_MEM*)0)

{

    OSMemFreeList=(OS_MEM*)OSMemFreeList->OSMemFreeList;

}

OS_EXIT_CRITICAL();

 if(pmem==(OS_MEM*)0)

{

    *err=OS_MEM_INVALID_PART;

     return((OS_MEM*)0);

}

OS_ENTER_CRITICAL();

pmem=OSMemFreeList;

if(OSMemFreeList!=(OS_MEM*)0)

{

      OSMemFreeList=(OS_MEM*)OSMemFreeList->OSMemFreeList;

}

OS_EXIT_CRITICAL();

if(pmem==(OS_MEM*)0)

{

    *err=OS_MEM_INVALID_PART;

     return((OS_MEM*)0);

}

plink=(void**)addr;

pblk=(INT8*)addr+blksize;

for(i=0;i<(nblks-1);i++)

{

    *plink=(void*)pblk;

    plink=(void**)pblk;

    pblk=pblk+blksize;

}

* plink=(void*)0;

 OS_ENTER_CRITICAL();

pmem->OSMemAddr=addr;

 pmem->OSMemFreeList=addr;

pmem->OSMemNBlks=nblks;

pmem->OSMemBlkSize=blksize;

OS_EXIT_CRITICAL();

 *err=OS_NO_ERR;

return(pmem);


}

该函数共有4个参数:内存分区的起始地址,分区的内存块总数,每个内存块的字节数和一个指向错误代码的指针。如果OSMemCreate()操作失败,

它将返回一个NULL指针,否则,它将返回一个指向空内存块控制指针,对内存管理的其它操作,OSMemGet ,OSMemPut OSMemQuery函数灯

都要通过该指针进行。


#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);


void main(void)

{

   OSInit();

   PC_DOSSaveReturn();

   PC_VectSet(uCOS,OSCtxSw);

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

   OSTaskCreate(StartTask,(void*)0;&StartTaskStk[TASK_STK_SIZE-1],0);//创建起始函数

   OSStart();

}

void StartTask(void *pdata)

{

 #if OS_CRITICAL_METHOD==3

   OS_CPU_SR  cpu_sr;

#endif


  INT16S  key;

 pdata=pdata;

  OS_ENTER_CRITICAL();

   OS_EXIT_CARITICAL();

   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(;;)

    {

          if(PC_GetKey(&key)==TRUE)

           {

if(key==0x1B)

               {

                      PC_DOSReturn()

               }

         }

           OSTimeDlyHMSM(0,0,3,0);

    }

}


void MyTask(void *pdata)

{

#if OS_CRITICAL_METHOD==3

   OS_CPU_SR  cpu_sr;

#endif

pdata=pdata;

 for(;;)

{

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

  IntBlkPtr=OSMemGet(IntBuffer,&err);//请求内存块  内存分区指针

   OSMemQuery(IntBuffer,&MemInfo);

  sprintf(s,"%x",MemInfo.OSFreeList);//显示头指针把得到的空闲内存块链表首地址的指针放到指针s在的空间

    if(Time>=5)

   {

       OSMemPut(//释放内存块函数

          IntBuffer,//内存块分区的指针

          IntBlkPtr //释放内存块指针)

  }

     Times++;

       OSTimeDlyHSM(0,0,1,0);//等待1s


}

}

void YouTask(void *pdata)

{

 #if OS_CRITICAL_METHOD==3

    OS_CPU_SR  cpu_sr;

#endif

  pdata=pdata;

  for(;;)

   {

InBlkPtr=OSMemGet(IntBuffer,&err);

         OSMemQuery(IntBuffer,&MemInfo);

         OSMemPut(IntBuffer,IntBlkPtr);

        OSTimeDlyHMSM(0,0,2,0);

   }

}

void HerTask(void *pdata)

{

#if OS_CRITICAL_METHOD==3

   OS_CPU_SR  cpu_sr;

#endif

  pdata=pdata;

  for(;;)

  {

        InBlkPtr=OSMemGet(IntBuffer,&err);

        OSMemQuery(IntBuffer,&MemInfo);

     OSMemPut(IntBuffer,IntBlkPtr);

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

   }

}

//根据上面的分析可以很容易分析的现象了,从现象中可以看出,任务YouTask和HerTask申请了内存块使用完了

就释放,而任务MyTask要一直到运行了6此后释放申请的内存块。





0 0