ucos-II的内存管理提供了对某块完整内存的修改,功能非常简单NBNC的代码大概只有200多行,在整个内核中也基本是独立的。它通过如下方式对内存块进行管理:
OS_MEM *mem; INT8U buff[16][128]; void main(void) { INT8U err; mem = OSMemCreate(&buff[0][0],16,128,&err); }
下文分析os_mem.c文件,从全局变量的定义与接口函数的实现两方面记录ucos-II的内存管理机制。
1. MEM的全局变量
OS_EXT OS_MEM *OSMemFreeList; /* Pointer to free list of memory partitions */ OS_EXT OS_MEM OSMemTbl[OS_MAX_MEM_PART]; /* Storage for memory partition manager */
上面两个全局变量在内核初始化中由OS_MemInit初始,用户试图进行管理的一个内存块,如上例中的buff,对应内核中的一个OS_MEM资源,OS_MEM结构体定义如下:
typedef struct { /* MEMORY CONTROL BLOCK */ void *OSMemAddr; /* Pointer to beginning of memory partition */ void *OSMemFreeList; /* Pointer to list of free memory blocks */ INT32U OSMemBlkSize; /* Size (in bytes) of each block of memory */ INT32U OSMemNBlks; /* Total number of blocks in this partition */ INT32U OSMemNFree; /* Number of memory blocks remaining in this partition */ } OS_MEM;
2. MEM的接口函数
plink = (void **)addr; //addr是内存分区的起始地址、blksize是内存分区中每个内存块的大小 pblk = (INT8U *)addr + blksize; for (i = 0; i < (nblks - 1); i++) { *plink = (void *)pblk; //相当于把pNext的地址复制给pCur的值 plink = (void **)pblk; pblk = pblk + blksize; } *plink = (void *)0; pmem->OSMemAddr = addr; pmem->OSMemFreeList = addr;
2. 主要接口函数诸如获取一个内存块或者释放一个内存块,都是对上述链表的操作。但由于链表的定义,链表的插入和删除变得很简单。例如返回一个内存块给内存分区:
*(void **)pblk = pmem->OSMemFreeList; //把当前的pFree作为pBlk的值 pmem->OSMemFreeList = pblk;//pblk赋值给pFree pmem->OSMemNFree++;
返回前:pData -> OSMemFreeList(old),
返回后: pData -> pblk -> OSMemFreeList(Old); pblk成为当前的OSMemFreeList(New)
获取一个内存块给内存分区:
pblk = pmem->OSMemFreeList; //当前空节点的地址返回 pmem->OSMemFreeList = *(void **)pblk; //当前空节点的值(即pNext)赋值给OSMemFreeList pmem->OSMemNFree--;
其他:OS_MEM_DATA 定义了一个内存块的信息,在OSMemQuery中使用,没有特别的意义。