uC/OS-II 内存管理

UC/OS-II  内存管理

1. 简介
    uC/OS-II 不使用ANSI编译器的malloc(), free(),因为内存碎片,很可能获取不到一块连续的内存, 这在嵌入式系统中是很危险的。同时malloc()和free()的执行时间也是不确定的。
    uC/OS-II 把内存划分为固定长度的块,一定数量的块组成一个partition,分配和回收的函数的执行时间是固定的,即常量时间。
    可以有一个或多个分区(partition), 每个分区的块大小可以不一样,这样想获取不同size的块,就从不同的分区取。再者,从哪个分区获取的块,回收时要重新放回获取内存时的分区,即哪来哪去。

2. 数据结构
    内存控制块:用于跟踪内存分区,每个分区使用自己的内存控制块

 typedef struct {
void *OSMemAddr;
void *OSMemFreeList;
INT32U OSMemBlkSize;
INT32U OSMemNBlks;
INT32U OSMemNFree;
} OS_MEM;

OSMemAddr       : 内存分区的起始地址,分区建立时初始化,以后不再改变
   OSMemFreeList : 指针,两种用途:1.指向下一个空闲的内存控制块,2.指向下一个空闲的内存块,视情况定    ** 要注意区分内存控制块和内存块**
   OSMemBlkSize  : 分区中内存块的大小
   OSMemNBlks     : 分区内内存块总数,分区建立时指定
   OSMemNFree    : 内存块的可用数,就是还剩多少个块可以分配。

两个选项:(OS_CFG.H)
   OS_MEM_EN               1  允许初始化内存管理器
   OS_MAX_MEM_PART   4  内存分区数,至少是2

图:

uC/OS-II 内存管理

这个链表由OSMemInit()建立,而OSMemInit()由OSInit()自动调用

3. 建立分区
    分区要先初始化才能使用, 建立分区由OSMemCreate()完成:

OS_MEM OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err);

算法描述:
       1. nblks >=2, blksize > sizeof(void *), 否则报错,返回(OS_MEM *)0;   
       2. 从OSMemFreeList取下一个内存控制块。因为一个分区需要一个内存控制块。
           验证一下不是空指针
           ** OSMemFreeList 是个全局变量 **, 指向上面图中的内存控制块链表头
       3.  将内存块连接起来,形成分区
       4.  初始化2中取出的内存控制块

简单点说, 这个函数的功能就是把空闲的内存块连接起来形成分区,再将分区相关信息放入内存控制块。
    代码这里就不粘出来了。 函数执行后, 内存分区如图:
uC/OS-II 内存管理

值得注意的是,这些内存块是通过每个块的前面几个字节作为连接地址的。这就是为什么blksize > sizeof(void *)

4. 获取内存块
    void * OSMemGet(OS_MEM *pmem, INT8U *err) ;

这个函数就是把内存控制块的OSMemFreeList所指向的内存块返回,然后OSMemFreeList(这个不是全局变量那个)指向下一个空闲内存块。

5. 返还内存块
    INT8U OSMemPut(OS_MEM *pmem, void * pblk);

用完了就返还内存块到链表里。 返还的位置还是OSMemFreeList.

6. 获取内存分区的状态
   INT8U OSMemQuery(OS_MEM *pmem, OS_MEM_DATA *pdata);

状态用一个结构来表示:

typedef struct {
void *OSAddr; /* 分区的起始地址 */
void *OSFreeList; /* 空闲块的起始地址 */
INT32U OSBlkSize; /* 内存块的size */
INT32U OSNBlks; /* 分区里块的总数 */
INT32U OSNFree; /* 空闲块的数量 */
INT32U OSNUsed; /* 使用块的数量 */
} OS_MEM_DATA;

将内存控制块的各字段,赋给OS_MEM_DATA的各字段,很简单。

上一篇:HTML & CSS 小总结


下一篇:jdk1.9之前的版本及jdk1.9环境变量的配置