uC/OS-II用于动态内存管理的函数有:创建动态内存区分函数OSMemCreate()、请求获得内存块函数OSMemGet()、释放内存块函数OSMemPut()和查询动态内存分区状态函数OSMemQueru()等函数。
- 创建动态内存分区
应用程序可通过调用函数OSMemCreate()来建立一个内存分区。该函数的原型如下:
OS_MEM *OSMemCreate(
void *addr,
INT32U nblks,
INT32U blksize,
INT8U *err
)
函数OSMemCreate()的流程图如图8-3所示。从图8-3中可以看到,函数首先对创建一个内存分区的基本条件做一系列的判断,在这一系列的条件判断中有两个问题值得注意:一是分区的内存块至少有两块;二是每个内存块的空间至少能存放一个指针,因为要在内存块中建立一个用于把分区内的内存块链表为一个链表的指针。
函数OSMemCreate()主要做了3个工作:首先自空内存控制块链表取一个控制块;然后把分区内的内存块接成链表建立内存分区;最后在把刚建立的内存分区的相关信息的填入内存控制块,并返回与这个刚建立的内存分区相关联的内存控制块的指针,以作为其他内存管理函数调用时的参数。
- 请求获得一个内存块
在应用程序需要一个内存块时,应用程序可以通过调用函数OSMemGet()向某内存分区请求获得一个内存块。该函数的原型如下:
void *OSMemGet(
OS_MEM *pmem, //内存分区的指针
INT8U *err //错误信息
)
函数OSMemGet中的参数pmem是应用程序希望获得的内存块所在内存分区所对应的内存控制的指针。函数调用成功后,其返回值为所请求的内存块指针。
函数OSMemGet的流程图如图8-4所示。
图 8-3 函数OSMemCreate()的流程图
图8-4 函数OSMemGet()的流程图
从中8-4可以看到,函数OSMemGet在判断应用程序传递来的内存控制块的指针为非NULL及内存分区尚在未被分配内存块后,就将内存块链表第一个块的指针OSMemFreeList赋给了指针pblk;然后就重新调整内存块链表,并使指针OSMemFreeList指向新的链表头;最后返回指针pblk。
需要注意的是,应用程序在调用函数OSMemGet()时,应该事先知道该分区中内存块的大小,并且在使用时不能超过该内存块长度,否则会引起灾难性的后果。
- 释放一个内存块
应用程序可以通过调用函数OSMemPut()来释放一个内存块。该函数的原型如下:
INT8U OSMemPut(
OS_MEM *pmem,
void *pblk //待释放内存块的指针
)
函数的OSMemPut()的流程图如图8-5所示。
需要注意的是,在调用函数OSMemPut()的一个内存块时,一定要确保把该内存块释放到它原来的所属的内存分区中,否则会引起灾难性的后果。
图8-5 函数OSMemPut()的流程图
- 查询一个内存块分区的状态
应用程序可以通过调用函数OSMemQuery()来查询一个分区目前的状态信息。该函数的原型如下:
INT8U OSMemQuery(
OS_MEM *pmem,
OS_MEM_DATA *pdata //存放分区状态的信息的结构的指针
)
其中,参数pdata是一个OS_MEM_DATA类型的结构。该结构的定义如下:
typedef struct {
void *OSAddr; //内存分区的指针
void *OSFreeList; //分区内内存块链表的头指针
INT32U OSBlkSize; //内存块的长度
INT32U OSNBlk; //分区内内存块的数组
INT32U OSNFree; //分区内空闲内存块的数目
INT32U OSNUsed; //已被分配的内存块的数目
}
调用函数OSMemQuery()后,内存分区的状态信息就存放在这个结构中。调用成功后,返回常数OS_NO_ERR.