uC/OS-II的内存管理
应用程序在运行中为了某种特殊需要,经常需要获得一些内存空间,因此作为一个完善的操作系统,必须具有动态分配内存的能力。对于实时操作来说,还应保证系统在动态内存分配时,它的执行时间是可确定的。
uC/OS-II对内存进行两级管理:把一片连续的内存空间分成了若干个分区;每个分区又分成了若干个大小相等的内存块。分区是操作系统的管理单位,而内存快时分配单位。内存分区及内存块的使用情况则由一个叫做内存控制块的表来记录。
如果应用程序要使用动态内存,则首先要在内存中划分出可进行动态分配的区域,这个划分出来的区域叫做内存分区。每个分区又要分为若干个叫做内存块的小区。uC/OS-II规定:同处一个分区的内存块的大小必须相等,而且同一个分区内存块的数据类型必须相同。为了使系统能够感知和有效地管理内存分区,uC/OS-II给每个内存分区定义一个叫内存控制块(OS_MEM)的数据结构。
#if OS_MEM_EN && (OS_MAX_MEM_PART >= 2)
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;
内存控制块的内存分区指针OSMemAddr指向了内存分区,内存分区中的各个内存块又组成了一个单向链表,内存控制块的链表指针OSMemFreeList就指向了这个单项链表的头。内存控制块的其他三个变量分别记录了分区中内存块的长度,总数目以及现在还未被分配的内存块数目。
与uC/OS-II中的其他控制块一样,在uC/OS-II初始化时,会调用内存控制块的初始化函数OSMemInit()定义并初始化一个空内存控制块链表。
uC/OS-II用于动态内存的管理的函数有:创建动态内存分区函数OSMemCreate(),请求获得内存块函数OSMemGet(),释放内存块函数OSMemPut()和查询动态内存分区状态函数OSMemQuery ()四个函数。
a) 创建内存分区
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
创建一个内存分区必须满足两个条件:一个是每个分区至少有两块内存块;二是内存块的空间至少能存放一个指针,这是因为要在内存块中建立一个用于把分区内的内存块链接为一个链表的指针。
在接下来的工作中,函数OSMemCreate()主要做了三项工作:首先自空内存控制块链表取一个控制块;然后把分区内的内存块链接成链表建立内存分区;最后再把刚建立的内存分区的相关信息添入内存控制块,并返回与这个刚建立的内存分区相关联的内存控制块的指针。
b) 请求获得一个内存块
void *OSMemGet (OS_MEM *pmem, INT8U *err)
参数pmem是应用程序希望获得的内存块所在内存分区对应的内存控制块的指针。函数调用成功后,其返回值为所请求的内存块指针。
需要注意的是,应用程序在调用函数OSMemGet()时,事先应知道该分区中内存块的大小,并且在使用该内存块是不能超过其长度,否则会引起灾难性的后果。当应用程序不再需要该内存块时,必须及时地将其释放。
c) 释放一个内存块
INT8U OSMemPut (OS_MEM *pmem, void *pblk)
需要注意的是,在调用函数OSMemPut的一个内存块时,一定要确保把该内存块释放到它原来所属的内存分区中,否则会引来灾难性的后果。
d) 查询一个内存分区的状态
INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *pdata)
其中参数pdata是一个OS_MEM_DATA类型的结构。该结构的定义如下:
typedef struct {
void *OSAddr; /* Pointer to the beginning address of the memory partition */
void *OSFreeList; /* Pointer to the beginning of the free list of memory blocks */
INT32U OSBlkSize; /* Size (in bytes) of each memory block */
INT32U OSNBlks; /* Total number of blocks in the partition */
INT32U OSNFree; /* Number of memory blocks free */
INT32U OSNUsed; /* Number of memory blocks used */
} OS_MEM_DATA;