为了消除碎片,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此后释放申请的内存块。