UCOSII学习---四、内存管理


一、基础知识:

在ANSIC中是使用malloc和free两个函数来动态分配和释放内存。例如在Linux系统中就是这样。但在嵌入式实时系统中,多次这样的操作会导致内存碎片,因为嵌入式系统尤其是uCOS是实地址模式,这种模式在分配任务堆栈时需要整块连续的空间,否则任务无法正确运行。且由于内存管理算法的原因,malloc和free的执行时间也是不确定。这点是实时内核最大的矛盾。
基于以上的原因uC/OS-II中把连续的大块内存按分区管理。每个分区中包含整数个大小相同的内存块,但不同分区之间的内存块大小可以不同。用户需要动态分配内存时,系统选择一个适当的分区,按块来分配内存。释放内存时将该块放回它以前所属的分区,这样能有效解决碎片问题,同时执行时间也是固定的。
同时uCOS-II根据以上的处理封装了适合于自己的动态内存分配函数OSMemGet()和OSMemPut(),但是使用这两个函数动态分配内存前需要先创建内存空间,也就是第二段咱们介绍的内存分块。

二、内存管理的函数

内存控制块的数据结构
Typedef
struct
{void   *osmemaddr    ;指向内存分区起始地址的指针。
void   *osmemfreelist  ;指向下一个空余内存控制块或者下一个空余内存块的指针,
Int32u  osmemblksize  ;内存分区中内存块的大小,是建立内存分区时定义的。
Int32u osmemnblks     ;内存分区中总的内存块数量,也是建立该内存分区时定义的。
Int32u  osmemnfree    ;内存分区块中当前获得的空余块数量。
}os_mem;
1: 建立一个内存分区,OSMemCreate()
OS_MEM *OSMemCreate (void *addr,  
                     INT32U nblks,   
                     INT32U blksize,   
                     INT8U *err)

OSMemCreate()函数的源代码。该函数共有4个参数:内存分区的起始地址、分区内的内存块总块数、每个内存块的字节数和一个指向错误信息代码的指针。err 是指向包含错误码的变量的指针。Err可能是如下几种情况:
* OS_NO_ERR :成功建立内存区域。
* OS_MEM_INVALID_ADDR :非法地址,即地址为空指针。
* OS_MEM_INVALID_PART :没有空闲的内存区域。
* OS_MEM_INVALID_BLKS :没有为内存区域建立至少两个内存块。
* OS_MEM_INVALID_SIZE :内存块大小不足以容纳一个指针变量。
如果OSMemCreate()操作失败,它将返回一个NULL指针。否则,它将返回一个指向内存控制块的指针。对内存管理的其它操作,像OSMemGet(),OSMemPut(),OSMemQuery()函数等,都要通过该指针进行。
每个内存分区必须含有至少两个内存块,每个内存块至少为一个指针的大小,因为同一分区中的所有空闲内存块是由指针串联起来的。接着,OSMemCreate()从系统中的空闲内存控制块中取得一个内存控制块,该内存控制块包含相应内存分区的运行信息。
OSMemCreate()必须在有空闲内存控制块可用的情况下才能建立一个内存分区。在上述条件均得到满足时,所要建立的内存分区内的所有内存块被链接成一个单向的链表。然后,在对应的内存控制块中填写相应的信息。完成上述各动作后,OSMemCreate()返回指向该内存块的指针。该指针在以后对内存块的操作中使用。

2:分配一个内存块,OSMemGet()

应用程序通过调用该函数,从已经建立的内存分区中申请一个内存块。该函数唯一的参数是指向特定内存分区的指针。

void *OSMemGet (OS_MEM *pmem, INT8U *err)

参数说明:pmem 是指向内存区域控制块的指针,可以从 OSMemCreate() 函数的返回值中得到。
err 是指向包含错误码的变量的指针。Err可能是如下情况:
* OS_NO_ERR :成功得到一个内存块。
* OS_MEM_NO_FREE_BLKS :内存区域中已经没有足够的内存块。
返回值:
OSMemGet() 函数返回指向所分配内存块的指针。如果没有可分配的内存块,OSMemGet() 函数返回空指针。

3:释放一个内存块,OSMemPut()

当应用程序不再使用一个内存块时,必须及时的把它释放,并放回到相应的内存分区中,这个操作就是通过调用该函数实现的。
该函数用于释放一个内存块,内存块必须释放回它原先所在的内存区域,否则会造成系统错误。

INT8U OSMemPut (OS_MEM *pmem, void *pblk);

参数说明:pmem 是指向内存区域控制块的指针,可以从 OSMemCreate() 函数的返回值中得到。
pblk 是指向将被释放的内存块的指针。
返回值:
OSMemPut() 函数的返回值为下述之一:
* OS_NO_ERR :成功释放内存块
* OS_MEM_FULL :内存区域已满,不能再接受更多释放的内存块。这种情况说明用户程序出现了错误,释放了多于用 OSMemGet() 函数得到的内存块。

4:查询一个内存分区的状态,OSQMemQuery()

该函数用于得到内存区域的信息。

INT8U OSMemQuery(OS_MEM *pmem, OS_MEM_DATA *pdata);

参数说明:pmem 是指向内存区域控制块的指针,可以从 OSMemCreate() 函数的返回值中得到。
pdata 是一个指向 OS_MEM_DATA 数据结构的指针。

猜你喜欢

转载自blog.csdn.net/ROM7RAM/article/details/81744224