《第五章动态内存管理优秀课件.ppt》由会员分享,可在线阅读,更多相关《第五章动态内存管理优秀课件.ppt(30页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第五章动态内存管理第1页,本讲稿共30页第五章 动态内存管理5.1 内存控制块l5.1.1 可动态分配内存的划分l5.1.2 内存控制块OS_MEM的结构l5.1.3 空内存控制块链表5.2 动态内存的管理l5.2.1 创建动态内存分区l5.2.2 请求获得一个内存块l5.2.3 释放一个内存块l5.2.4 查询一个内存分区的状态第2页,本讲稿共30页5.1 内存控制块uC/OS-II对内存斤西瓜两级管理,即把一个连续的内存空间分为若干个分区,每个分区又分为若干个大小相等的内存块。操作系统以分区为单位来管理动态内存,而任务以内存块为单位来获得和释放动态内存。内存分区及内存块的使用情况则由内存控
2、制块来记录第3页,本讲稿共30页5.1.1 可动态分配内存的划分1.内存块:uC/OS-II以内存块为单位向应用程序提供动态内存。内存块的大小可由用户定制2.内存分区:大小相等的多个内存块可以组成一个内存分区。内存分区是系统对内存进行管理的基本单位3.内存分区与内存块的定义:在内存中定义一个内存分区及其内存块的方法很简单,只要定义一个二维数组即可如:INT16U IntMemBuf1010第4页,本讲稿共30页上面定义的只是在内存中划分出了分区及内存块的区域,还不是一个真正的可以动态分配的内存区(如图5.1a)只有把内存控制块与分区关联起来之后,系统才能对其进行相应的管理和控制,才是一个真正的
3、动态内存区(如图5.1b)第5页,本讲稿共30页5.1 a 没有控制块时的分区 b 有控制块时的分区第6页,本讲稿共30页5.1.2 内存控制块OS_MEM的结构为了是系统能够感知和有效管理内存分区,uC/OS-II定义了一个叫做内存控制块(OS_MEM)的数据结构。系统就用这个内存控制块来记录和跟踪每一个内存分区的状态第7页,本讲稿共30页内存控制块的内存分区指针OSMemAddr指向了内存分区,内存分区中的各个内存块又组成了一个单项链表,内存控制块的链表指针OSMemFreeList就指向了这个单向链表的头内存控制块的其他3个变量分别记录了分区中内存块的长度,总数目以及现在还为被分配的内存
4、块数目第8页,本讲稿共30页5.1.3 空内存控制块链表与uC/OS-II其他控制块一样,在uC/OS-II初始化时,会调用内存控制块的初始化函数OS_MemInit()定义并初始化一个空内存控制块链表在这个空内存控制块链表中,一共有OS_MAX_MEM_PART(在文件OS_CFG.H中定义的常数)个空内存控制块。这些空内存控制块的指针成员OSMemFreeList暂时作为指向下一个空内存控制块的指针第9页,本讲稿共30页空内存控制块链表第10页,本讲稿共30页每当应用程序需要创建一个内存分区时,系统就会从空内存控制块链表中摘取一个控制块,而把链表的头指针OSMemFreeList指向下一个
5、空内存控制块每当应用程序释放一个内存分区时,则会把该分区对应的内存控制块归还给空内存控制块链表第11页,本讲稿共30页5.2 动态内存的管理用于动态内存管理的函数有:创建动态内存分区函数请求获得内存块函数释放内存块函数查询动态内存分区状态函数第12页,本讲稿共30页5.2.1 创建动态内存分区应用程序可以通过OSMemCreate()来建立一个内存分区OS_MEM*OSMemCreate(lvoid*addr,/内存分区的起始地址lINT32U nblks,/分区中内存块的数目lINT32U blksize,/每个内存块的字节数lINT8U*err/错误信息l)第13页,本讲稿共30页第14页
6、,本讲稿共30页在各类判断条件中有两个问题值得注意:1.分区的内存块至少有两块2.每个内存块的空间至少能存放一个指针,因为要在内存块中建立一个用于把分区内的内容块连接为一个链表的指针第15页,本讲稿共30页例如:5.1 建立一个含有50个内存块并且每块的长度为64字节的内存分区。试写出主要代码:第16页,本讲稿共30页/定义全局变量OS_MEM*CommTxBuffer;/定义内存分区指针INT8U CommTxPart5064;/定义分区和内存块INT8U err;/在主函数的适当位置建立内存分区void main(void)lOSInit();l.lCommTxBuffer=OSMemCr
7、eate(CommTxPart,/内存分区的首地址50,/分区内存块的数目64,/每个内存块的长度&err);l.lOSStart()第17页,本讲稿共30页5.2.2 请求获得一个内存块在应用程序需要一个内存块时,应用程序可以通过调用函数OSMemGet()向某内存分区请求获得一个内存块。该函数的原型如下:void*OSMemGet(lOS_MEM*pmem,/内存分区指针lINT8U*err/错误信息);参数pmem试应用程序希望获得的内存块所在内存分区所对应的内存控制块的指针第18页,本讲稿共30页第19页,本讲稿共30页函数OSMemGet()在判断应用程序传递来的内存控制块的指针为非
8、NULL及内存分区尚存在未被分配的内存块后,就将内存块链表的第一块的指针OSMemFreeList献给了指针pblk;然后就重新调整内存块链表,并使指针OSMemFreeList指向新的链表头;最后返回指针pblk.当函数调用失败,返回null第20页,本讲稿共30页例:在5.1基础上写出任务MyTask请求一个内存块的代码第21页,本讲稿共30页/定义全局变量OS_MEM*CommTxBuffer;/定义内存分区指针INT8U CommTxPart5064;/定义分区和内存块INT8U err;INT8U*BlkPtr;/定义内存块指针定义内存块指针/在主函数的适当位置建立内存分区void
9、main(void)l同前/在任务MyTask的合适位置请求内存块void MyTask(void*)pdata)l.lfor(;)lBlkPtr=OSMemGet(lCommTxBuffer,/内存分区的指针l&err/错误信息l);.第22页,本讲稿共30页需要注意的是,应用程序在调用函数OSMemGet()时,应该事先知道该分区中内存块的大小,并且在使用时不能超过改内存块长度,否则会引起灾难性的后果第23页,本讲稿共30页5.2.3 释放一个内存块当应用程序不再使用一个内存块时,必须及时地将其释放应用程序通过调用函数OSMemPut()来释放一个内存块INT8U OSMemPut(lOS
10、_MEM*pmem,/内存块所属内存分区的指针lvoid*pblk/待释放内存块的指针);第24页,本讲稿共30页函数返回值是错误信息。如果函数调用成功,返回信息OS_NO_ERR;否则根据具体错误将返回OS_MEM_INVALID_PMEM(控制块指针为空指针),OS_INVALID_PBLK(释放内存块指针为空指针)和OS_MEM_FULL(分区已满)需要注意的是,在调用该函数的一个内存块时,一定要确保把该内存块释放到它原来所属的内存分区中,否则会引起灾难性的后果第25页,本讲稿共30页第26页,本讲稿共30页5.2.4 查询一个内存分区的状态应用程序可以通过调用函数OSMemQuery(
11、)来查询一个分区目前的状态信息。INT8U OSMemQuery(lOS_MEM*pmem,/待查询的内存控制块的指针lOS_MEM_DATA*pdata/存放分区状态信息的结构指针);调用该函数后,内存分区的状态信息存放到 pdata中成功后,返回OS_NO_ERR第27页,本讲稿共30页第28页,本讲稿共30页练习试设计一个有3个任务的应用程序,这3个任务分别是MyTask,YouTask和HerTask。在应用程序中创建一个动态内存分区,该分区有8个内存块,每个内存块的长度为6字节。应用程序的任务YouTask和HerTask都在任务运行后请求一个内存块,随后就释放它;任务MyTask也在任务运行后请求一个内存块,但是要在任务MyTask运行6次后,才释放它所申请的内存块为了了解内存分区变化的情况,编写代码来观察分区头指针和已被使用内存块的个数第29页,本讲稿共30页第30页,本讲稿共30页