现在的位置: 首页 > 综合 > 正文

ucos-II 内存管理源码分析

2012年04月09日 ⁄ 综合 ⁄ 共 1680字 ⁄ 字号 评论关闭

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的接口函数

  1. 建立内存分区OSMemCreate:在该函数中一个空闲的OS_MEM资源通过OSMemFreeList被获取,同时这个内存分区内的内存块被初始化为一个起始地址是OSMemAddr的链表。我认为这个链表的定义是非常巧妙的,当前节点的值存储下一个节点的地址,一次类推,代码如下(映像中linux内核中的万用链表也是类似的机制):
    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中使用,没有特别的意义。

 

 

抱歉!评论已关闭.