ucos内存的动态分配

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
内存
内存块1 内存块2 内存块3 …… …… 内存块5
一 个 内 存 分 区
图1 内存控制块与内存分区和内存块的关系1-没有控制块时的分区
只有当把内存控制块与分区关联起来之后,系统才能对其进行相应的管理和 控制。它才是一个真正的动态内存区。
1.2 内存控制块OS_MEM的结构
内存控制块的结构:
void main(void) { INT8U err; …… OsInit(); …… CommTxBuffer = OSMemCreate(CommTxPart,50,64,*err); …… OSStart(); 需要注意的是:应用程序在调用函数OSMemGet()时, } 应该事先知道该分区中内存块的大小,并且在使用该 内存块时不能超其长度,否则会引起灾难性的后果。 void MyTask( (void *)pdata ) 当应用程序不再需要该内存块时,必须及时将其释放。 { …… for(;;){ …… BlkPtr = OSMemGet(CommTxBuffer,&err); …… } }
应用程序在运行中为了某种特殊需要,经常需要临时获得一些内存空间。因 此作为比较完善的操作系统,必须具有动态分配内存的能力。 能否合理、有效的对内存进行分配和管理,是衡量一个操作系统品质的指标 之一。特别对于实时操作系统,应该保证系统在动态分配内存时,它的执行 时间必须是可确定的。
uC/OS-II改进了ANSI C用来动态分配和释放内存的函数malloc()和free(),使他 们可以对大小固定的内存进行操作,从而使函数malloc()和free()执行时间成为 可确定的,满足了实时操作系统的要求。
*err=OS_MEM_INVALID_PART 返回空指针NULL
在内存控制块中 填写刚建立分区的信息
返回内存控制块指针pmem
yes
OSMemFreeList!= NULL?
no
yes
图4 函数OSMemCreate()流程图
返回
例1
建立一个含有50个内存块并且每块的长度为64字节的内存分区。试 写出主要代码。
// 内存分区的指针 // 错误信息
使指针OSMemFrereList指 向新的链表头
pmem != NULL?
yes
内存分区尚 存在未被分 配的内存块
pmem->OSNMemFree>0?
yes Pblk=pmem->OSMemFreeList
将内存块链表的第一个块的 指针OSMemFrereList赋给了 指针pblk
OS_MEM INT8U INT8U *CommTxBuffer; CommTxPart[50][64]; err; // 定义内存分区指针 // 定义分区和内存块
void main(void) { INT8U err; …… OsInit(); …… CommTxBuffer = OSMemCreate( CommTxPart, 50, 64, *err …… OSStart(); } );
例3
设计一个含有3个任务的应用程序,这3个任务分别是MyTask、YouTask和 HerTask。在应用程序中创建一个动态内存分区,该分区有8个内存块,每个内 存块的长度为6个字节。应用程序的任务YouTask和HerTask都在任务运行后请求 一个内存块,随后就释放它。任务MyTask也在任务运行后请求一个内存块,但 是要在任务MyTask运行6次后,才释放它所申请的内存块。 为了了解内存分区变化的情况,编写代码来观察分区头指针和已被使用内 存块的个数。
// 内存分区的起始地址 // 分区中内存块的数目 // 每个内存块的字节数 // 错误信息
Addr != NULL?
yes
分区的内存块 至少有2块 每个内存块的 空间得至少能 存放一个指针
nblks > 1?
no
yes no
blksize >= sizeof(void*)?
*err=OS_MEM_INVALID_SIZE 返回空指针NULL
typedef struct{ void *OSMemAddr; void *OSMemFreeList; INT32U OSMemBlkSize; INT32U OSMemNBlks; INT32U OSMemNFree; }OS_MEM;
OSMemAddr OSMemFreeList OSMemBlkSize OSMemNBlks OSMemNFree
图2 内存控制块与内存分区和内存块的关系2-有控制块时的分区
1.3 空内存控制块链表
uC/OS-II初始化时,会调用内存初始化函数OS_MemInit()定义并初始化一个空 内存控制块链表。 每当应用程序需要创建一个内存分区时,系统就会从空内存控制块链表中摘 取一个控制块,而把链表的头指针OSMemFreeList指向下一个空内存控制块;而 每当应用程序释放一个内存分区时,则会把该分区对应的内存控制块归还给空 内存控制块链表。
图6 函数OSSemPut()流程图
2 动态内存的管理(续)
查询一个内存分区的状态
INT8U OSMemQuery( OS_MEM *pmem, OS_MEM_DATA *pdata ); // 待查询的内存控制块的指针 // 存放分区状态信息的结构的指针
OS_MEM_DATA结构如下:
typedef struct { void *OSAddr; void *OSFreeList; INT32U OSBlkSize; INT32U OSNBlks; INT32U OSNFree; INT32U OSNUsed; } OS_MEM_DATA; // 内存分区的指针 // 分区内内存块链表的头指针 // 内存块的长度 // 分区内内存块的数目 // 分区内空闲内存块的数目 // 已被分配的内存块的数目
// 内存所属内存分区的指针 // 待释放内存块的指针
pmem != NULL?
yes
pblk != NULL?
no
返回OS_MEM_INVALID_PBLK
yes
需要注意的是,在调用函数OSMemPut()时,一定要 确保把该内存块释放到它原来所属的内存分区中, 否则会引起灾难性后果。 对例2中任务MyTask使用的内存块进行释放
1.1 可动态分配内存的划分
在内存中划分一个内存分区与内存块的方法: INT16U IntMemBuf[5][10];
uC/OS-II要求同一个分区中内存块的字节 数必须相等,而且每个分区与该分区内存 块的数据类型必须相同。
注意:上面这个定义只是在内存中划分出了分区及内存块的区域,还不是一个真正的 可以动态分配的内存区!
0
Biblioteka Baidu
共OS_MAX_MEM_PART个内存分区
图3 空内存控制块链表
在OS-CFG.H中定义的常数
2 动态内存的管理
创建动态内存分区
OS_MEM *OSMemCreate( void *addr, INT32U nblks, INT32U blksize, INT8U *err );
进入 no *err=OS_MEM_INVALID_ADDR 返回空指针NULL *err=OS_MEM_INVALID_BLKS 返回空指针NULL 自空内存控制块链表 取一个空内存控制块 将分区中的所有内存 块链接为单向链表
// 内存分区的指针(指向分区的起始地址) // 内存控制块链表的指针 // 内存块的长度 // 分区内内存块的数目 // 分区内当前可分配的内存块数目
内存
下一个内存块的指针 内存块1
下一个内存块的指针
内存块2
内存控制块OS_MEM
…… 下一个内存块的指针 …… 内存块n
内 存 分 区
0
从图中可知,内存控制块的内 存分区指针OSMemAddr指向了 内存分区,内存分区中的各个 内存块又组成了一个单向链表, 内存控制块的链表指针 OSMemFreeList就指向了这个 单向链表的头。
2 动态内存的管理(续)
释放一个内存块
INT8U OSMemPut( OS_MEM *pmem, void *pblk );
进入 no 返回OS_MEM_INVALID_PMEM 链表头指针OSMemFreeList 指向释放的内存块 Pmem->OSMemNFree++ 返回OS_NO_ERR
练习1
设计一个有两个任务的应用程序,其中一个任务用来进行两个随机数的加 法运算,另一个任务则用来显示结果,要求加法运算的和存放在动态内存中。
例程3 结果
3 小结
通过定义一个二维数组就可在内存中划分出一个内存分区,并保证分区中的所 有内存块大小相等。 系统是通过与内存分区相关联的内存控制块来实现对内存分区的管理的。 划分及创建内存分区是应用程序根据需要由应用程序来负责的,而系统只提供 了可供任务调用的相关函数。 在uC/OS-II中,应用程序在释放使用的动态内存时的安全性是由用户应用程序 来维护的。
// 内存分区的首地址 // 分区内内存块的数目 // 每个内存块的长度
2 动态内存的管理(续)
请求获得一个内存块
void * OSMemGet( OS_MEM *pmem, INT8U *err );
进入 no *err=OS_MEM_INVALID_PMEM 返回空指针NULL 调整区内的内存块链表 no *err=OS_MEM_NO_FREE_BLKS 返回空指针NULL pmem->OSMemNFree-*err=OS_NO_ERR 返回分配给应用程序 的内存块指针pblk
OSMemFreeList
OSMemAddr OSMemFreeList OSMemBlkSize OSMemNBlks OSMemNFree OSMemAddr OSMemFreeList OSMemBlkSize OSMemNBlks OSMemNFree OSMemAddr OSMemFreeList OSMemBlkSize OSMemNBlks OSMemNFree
内存的动态分配
3 Sept. 2008 Confidential
1
内存的动态分配
目标: 本章旨在介绍内存的数据结构及操作,通过本章的学习,应该掌握如 下知识: uC/OS-II对内存的分区及分块 描述内存块的数据结构-内存控制块 内存控制块与内存分区之间的关系 对内存的操作
1 内存控制块
uC/OS-II对内存进行两级管理:把连续内存分成若
干个分区,每个分区又分成若干个大小相等的内存块 来进行管理。 操作系统以分区为单位来管理动态内存,而任务以 内存块为单位来获得和释放动态内存。 内存分区及内存块的使用情况由内存控制块来记录。
在ANSI C中可以用malloc()和 free()两个函数动态地分配内存和 释放内存。但是,在嵌入式实时操 作系统中,多次这样做会把原来很 大的一块连续内存区域,逐渐地分 割成许多非常小而且彼此又不相邻 的内存区域,也就是内存碎片。由 于这些碎片的大量存在,使得程序 到后来连非常小的内存也分配不到
图5 函数OSSemGet()流程图
例2
在例1的基础上写出任务MyTask请求一个内存块的代码。
OS_MEM INT8U INT8U INT8U *CommTxBuffer; CommTxPart[50][64]; err; *BlkPtr; // 定义内存分区指针 // 定义分区和内存块 // 定义内存块指针
相关文档
最新文档