Ucos II 内存管理
在mcu21的项目里,暂时还没用到内存管理。不过还是有必要学习一下的。
为了消除内存碎片,ucos II 把连续的大块内存按分区来管理。每个分区中包含有整数个大小相同的内存块。
.OSMemAddr是指向内存分区起始地址的指针。它在建立内存分区OSMemCreate()时被初始化,在此之后就不能更改了。
.OSMemFreeList是指向下一个空闲内存控制块或者下一个空闲的内存块的指针,具体含义要根据该内存分区是否已经建立来决定。
.OSMemBlkSize是内存分区中内存块的大小,是用户建立该内存分区时指定的。
.OSMemNBlks是内存分区中总的内存块数量,也是用户建立该内存分区时指定的。
.OSMemNFree是内存分区中当前可以得空闲内存块数量。
该函数共有4个参数:内存分区的起始地址、分区内的内存块总块数、每个内存块的字节数和一个指向错误信息代码的指针。如果OSMemCreate()操作失败,它将返回一个NULL指针。否则,它将返回一个指向内存控制块的指针。对内存管理的其它操作,象OSMemGet(),OSMemPut(),OSMemQuery()函数等,都要通过该指针进行。
在mcu21的理解中,以上程序,简单来说,主要执行以下两大步骤,一是从空闲内存控制块中获取一个内存控制块,二是初始化这块内存控制块。
在mcu21的项目里,暂时还没用到内存管理。不过还是有必要学习一下的。
为了消除内存碎片,ucos II 把连续的大块内存按分区来管理。每个分区中包含有整数个大小相同的内存块。
类似每个任务对应一个任务控制块,每个事件对应一个事件控制块,ucos II里每个内存块也是对应一个内存控制块。内存控制块是一个数据结构,定义如下:
- typedef struct {
- void *OSMemAddr;
- void *OSMemFreeList;
- INT32U OSMemBlkSize;
- INT32U OSMemNBlks;
- INT32U OSMemNFree;
- } OS_MEM;
- typedef struct {
- void *OSMemAddr;
- void *OSMemFreeList;
- INT32U OSMemBlkSize;
- INT32U OSMemNBlks;
- INT32U OSMemNFree;
- } OS_MEM;
.OSMemAddr是指向内存分区起始地址的指针。它在建立内存分区OSMemCreate()时被初始化,在此之后就不能更改了。
.OSMemFreeList是指向下一个空闲内存控制块或者下一个空闲的内存块的指针,具体含义要根据该内存分区是否已经建立来决定。
.OSMemBlkSize是内存分区中内存块的大小,是用户建立该内存分区时指定的。
.OSMemNBlks是内存分区中总的内存块数量,也是用户建立该内存分区时指定的。
.OSMemNFree是内存分区中当前可以得空闲内存块数量。
完整地使用内存,需要经过以下步骤:
1. 建立一个内存分区(OSMemCreate())
2. 调用OSMemGet()函数从已经建立的内存分区中申请内存块
3. 当用户应用程序不再使用一个内存块时,调用OSMemPut()释放内存。
4. 在这过程中可以调用OSMemQuery()查询一个内存分区的状态
建立一个内存分区需要使用ucos II 系统函数OSMemCreate()。实现过程如下:
- OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
- {
- OS_MEM *pmem;
- INT8U *pblk;
- void **plink;
- INT32U i;
- if (nblks < 2) { (1)
- *err = OS_MEM_INVALID_BLKS;
- return ((OS_MEM *)0);
- }
- if (blksize < sizeof(void *)) { (2)
- *err = OS_MEM_INVALID_SIZE;
- return ((OS_MEM *)0);
- }
- OS_ENTER_CRITICAL();
- pmem = OSMemFreeList; (3)
- if (OSMemFreeList != (OS_MEM *)0) {
- OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
- }
- OS_EXIT_CRITICAL();
- if (pmem == (OS_MEM *)0) { (4)
- *err = OS_MEM_INVALID_PART;
- return ((OS_MEM *)0);
- }
- plink = (void **)addr; (5)
- pblk = (INT8U *)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; (6)
- pmem->OSMemFreeList = addr;
- pmem->OSMemNFree = nblks;
- pmem->OSMemNBlks = nblks;
- pmem->OSMemBlkSize = blksize;
- OS_EXIT_CRITICAL();
- *err = OS_NO_ERR;
- return (pmem); (7)
该函数共有4个参数:内存分区的起始地址、分区内的内存块总块数、每个内存块的字节数和一个指向错误信息代码的指针。如果OSMemCreate()操作失败,它将返回一个NULL指针。否则,它将返回一个指向内存控制块的指针。对内存管理的其它操作,象OSMemGet(),OSMemPut(),OSMemQuery()函数等,都要通过该指针进行。
在mcu21的理解中,以上程序,简单来说,主要执行以下两大步骤,一是从空闲内存控制块中获取一个内存控制块,二是初始化这块内存控制块。