ucos II 内核学习之七:内存管理

 Ucos II 内存管理
     在mcu21的项目里,暂时还没用到内存管理。不过还是有必要学习一下的。
    为了消除内存碎片,ucos II 把连续的大块内存按分区来管理。每个分区中包含有整数个大小相同的内存块。

    类似每个任务对应一个任务控制块,每个事件对应一个事件控制块,ucos II里每个内存块也是对应一个内存控制块。内存控制块是一个数据结构,定义如下:

[cpp]  view plain copy
  1. typedef struct {  
  2.     void   *OSMemAddr;  
  3.     void   *OSMemFreeList;  
  4.     INT32U  OSMemBlkSize;  
  5.     INT32U  OSMemNBlks;  
  6.     INT32U  OSMemNFree;  
  7. } OS_MEM;  
  8.   
  9.     
  10. typedef struct {  
  11.     void   *OSMemAddr;  
  12.     void   *OSMemFreeList;  
  13.     INT32U  OSMemBlkSize;  
  14.     INT32U  OSMemNBlks;  
  15.     INT32U  OSMemNFree;  
  16. } OS_MEM;  

.OSMemAddr是指向内存分区起始地址的指针。它在建立内存分区OSMemCreate()时被初始化,在此之后就不能更改了。
.OSMemFreeList是指向下一个空闲内存控制块或者下一个空闲的内存块的指针,具体含义要根据该内存分区是否已经建立来决定。
.OSMemBlkSize是内存分区中内存块的大小,是用户建立该内存分区时指定的。
.OSMemNBlks是内存分区中总的内存块数量,也是用户建立该内存分区时指定的。
.OSMemNFree是内存分区中当前可以得空闲内存块数量。


完整地使用内存,需要经过以下步骤:
1.     建立一个内存分区(OSMemCreate())
2.     调用OSMemGet()函数从已经建立的内存分区中申请内存块
3.     当用户应用程序不再使用一个内存块时,调用OSMemPut()释放内存。
4.     在这过程中可以调用OSMemQuery()查询一个内存分区的状态
 
建立一个内存分区需要使用ucos II 系统函数OSMemCreate()。实现过程如下:

[cpp]  view plain copy
  1. OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)  
  2. {  
  3.     OS_MEM  *pmem;  
  4.     INT8U   *pblk;  
  5.     void   **plink;  
  6.     INT32U   i;  
  7.    
  8.    
  9.     if (nblks < 2) {                                                   (1)  
  10.         *err = OS_MEM_INVALID_BLKS;  
  11.         return ((OS_MEM *)0);  
  12.     }  
  13.     if (blksize < sizeof(void *)) {                                    (2)  
  14.         *err = OS_MEM_INVALID_SIZE;  
  15.         return ((OS_MEM *)0);  
  16.     }  
  17.     OS_ENTER_CRITICAL();  
  18.     pmem = OSMemFreeList;                                              (3)  
  19.     if (OSMemFreeList != (OS_MEM *)0) {  
  20.         OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;  
  21.     }  
  22.     OS_EXIT_CRITICAL();  
  23.     if (pmem == (OS_MEM *)0) {                                         (4)  
  24.         *err = OS_MEM_INVALID_PART;  
  25.         return ((OS_MEM *)0);  
  26.     }  
  27.     plink = (void **)addr;                                             (5)  
  28.     pblk  = (INT8U *)addr + blksize;  
  29.     for (i = 0; i < (nblks - 1); i++) {  
  30.         *plink = (void *)pblk;  
  31.         plink  = (void **)pblk;  
  32.         pblk   = pblk + blksize;  
  33.     }  
  34.     *plink = (void *)0;  
  35.     OS_ENTER_CRITICAL();  
  36.     pmem->OSMemAddr     = addr;                                        (6)  
  37.     pmem->OSMemFreeList = addr;  
  38.     pmem->OSMemNFree    = nblks;  
  39.     pmem->OSMemNBlks    = nblks;  
  40.     pmem->OSMemBlkSize  = blksize;  
  41.     OS_EXIT_CRITICAL();  
  42.     *err   = OS_NO_ERR;  
  43.     return (pmem);                                                     (7)  

        该函数共有4个参数:内存分区的起始地址、分区内的内存块总块数、每个内存块的字节数和一个指向错误信息代码的指针。如果OSMemCreate()操作失败,它将返回一个NULL指针。否则,它将返回一个指向内存控制块的指针。对内存管理的其它操作,象OSMemGet(),OSMemPut(),OSMemQuery()函数等,都要通过该指针进行。
在mcu21的理解中,以上程序,简单来说,主要执行以下两大步骤,一是从空闲内存控制块中获取一个内存控制块,二是初始化这块内存控制块。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值