毕业论文μCOSII下任务调度的实验方法.doc

上传人:laozhun 文档编号:3972782 上传时间:2023-03-30 格式:DOC 页数:26 大小:487KB
返回 下载 相关 举报
毕业论文μCOSII下任务调度的实验方法.doc_第1页
第1页 / 共26页
毕业论文μCOSII下任务调度的实验方法.doc_第2页
第2页 / 共26页
毕业论文μCOSII下任务调度的实验方法.doc_第3页
第3页 / 共26页
毕业论文μCOSII下任务调度的实验方法.doc_第4页
第4页 / 共26页
毕业论文μCOSII下任务调度的实验方法.doc_第5页
第5页 / 共26页
点击查看更多>>
资源描述

《毕业论文μCOSII下任务调度的实验方法.doc》由会员分享,可在线阅读,更多相关《毕业论文μCOSII下任务调度的实验方法.doc(26页珍藏版)》请在三一办公上搜索。

1、C/OS-II下任务调度的实验方法作者姓名: 指导教师:摘要:C/OS-II是一个基于抢占式的实时多任务内核,其优点就是代码量小、便于移植和维护,从而得到了广泛的应用和研究。而任务调度是一个实时操作系统的核心功能,关系到整个操作系统的性能。本文对C/OS-II的任务调度通过实验的方式让读者更加直观的了解C/OS-II下的任务调度,C/OS-II内核基于优先级的抢占式调度算法,本文系统的分析了任务调度的具体流程,设计了任务调度的实验方法,编写一段源程序运行并得到结果。关键词:抢占式;任务调度;实验 1引言C/OS-II是一个完整的,可移植,可固化,可剪裁的嵌入式实时操作系统。它采用占先式调度方式

2、,即最高优先级的任务一旦就绪,总能立刻得到CPU的使用权,从而保证系统的实时性。在任务调度过程中,C/OS-II内核能快速、准确的从众多的就绪态任务中找出优先级最高的任务,减少系统的响应时间,保证系统的实时性。本文首先介绍与任务有关的概念和有关任务调度重要的域,接着详细分析C/OS-II的最高优先级查找算法和任务调度原理并结合实例加以说明。在分析最高优先级查找算法时首先分析将任务置于就绪态的过程,这样更抑郁理解内核的查找。接着讨论为实时操作系统C/OS-II下任务调度设计出实验方法并运行一段源程序同时得到的结果。 2整体研究思路 作者首先介绍与任务有关的概念和有关任务调度重要的域,接着详细分析

3、C/OS-II的最高优先级查找算法和任务调度原理并结合实例加以说明。在分析最高优先级查找算法时首先分析将任务置于就绪态的过程,这样更抑郁理解内核的查找。接着讨论为实时操作系统C/OS-II下任务调度设计出实验方法并运行一段源程序同时得到的结果 3嵌入式实时操作系统C/OS-II31C/OS-II简介C/OS-II是一个公开源代码的抢占先式多任务的微内核实时操作系统。其特点概括为:源代码公开,代码结构清晰;可移植性好;可裁剪性;内核属于抢占式;它可以管理64个任务。C/OS-II提供很多系统服务,例如邮箱、消息队列、信号量、块大小固定的内存的申请与释放、时间相关函数等。C/OS-II自1992年

4、的第一版(C/OS)以来已经有几百个应用,是一个经实践证明好用且稳定可靠的内核。其代码量很少,而且以条件编译的形式来实现各部分功能,在最大程度上减少对存储空间的浪费,非常适合低端嵌入。32C/OS-II组件321任务管理一个任务通常是一个无限的循环,由程序和数据组成。在C/OS-II中,任务有5种状态:休眠态、就绪态、运行态、中断态、等待态,在任意时刻,任务处于这5种状态之一。C/OS-II对任务的管理和调度主要是通过任务控制块OS_TCB和任务就绪表来实现。OS_TCB是一个数据结构,与任务一一对应,它包括任务指针,任务堆栈信息,任务优先级,任务状态,任务在任务就绪表中的位置等信息。在操作系

5、统初始化时,系统申请了一块RAM空间来存储空闲OS_TCB。一旦任务建立,系统就会分配一个OS_TCB给该任务。当任务的CPU使用权被剥夺时,C/OS-II用它来保存该任务的状态。当任务重新得到CPU使用权时,OS_TCB能确保任务从被中断的那一点继续执行下去。OS_TCB全部驻留在RAM中,在任务建立的时候,它被初始化。应用程序中最多任务数是在文件OS_CFG.H中定义的,所有的任务控制块OS_TCBs都是放在任务控制块列表数组OS_TCBTbl中的。C/OS-II占用了两个任务,一个用于空闲任务,另一个用于任务统计。在C/OS-II初始化时, OS_TCBs被链接成空任务控制块的单向链表。

6、当任务一旦建立,空任务块指针OSTCBFreeList指向的OS_TCB便赋给了该任务,然后OSTCBFreeList的值调整为指向链表中下一个空的任务控制表。一旦任务被删除,它的任务控制块就回到空任务控制块链表中。C/OS-II对任务的管理是通过一系列函数改变任务控制块的链表和数组以及改变任务控制块的信息实现。C/OS-II任务的调度是基于优先级的调度,通过就绪表来实现,每个任务被赋予一个优先级,优先级高的任务先运行,反之亦然。就绪表中有两个变量OSRdyGrP和OSRdyTbl。任务按优先级分组,8个任务为一组,OSRdyGrP中的每一位表示8组任务中每一组中是否有进入就绪态的任务,同样,

7、任务进入就绪态时,就绪表OSRdyTbl中的相应元素的相应位也置位。322时间管理C/OS-II(其他内核也一样)要求用户提供定时中断来实现延时与超时控制等功能,这个定时中断叫时钟节拍,它应该每秒发生10至100次。时钟节拍的频率实际上是由用户应用程序决定的,时钟频率越高,系统的负荷就越重。时间管理提供如下功能:产生时钟节拍、任务延时、结束延时、系统时间。323任务之间的通讯与同步大多数操作系统中,通常用多个任务来完成一个复杂任务,这就要考虑任务之间的通讯与同步。在C/OS-II中,任务之间通讯的方法有三种:信号量、邮箱、消息对列,它们被看作是事件,用一个数据结构来表示,称为事件控制块。所有的

8、事件控制块组成一个事件控制块链表或数组,该链表或数组在C/OS-II初始化时建立。C/OS-II对信号量、邮箱、消息对列的操作是通过一系列的函数来实现的。324内存管理在C/OS-II中,操作系统把连续的大块内存按分区来管理,每个分区中包含有整数个大小相同的内存块。这样,用户的应用程序就可以根据不同的应用从不同的内存分区中得到不同大小的内存块,当特定的内存块释放时必须重新放回它以前所属的内存分区。显然,这种方法简化了内存分区算法,也解决了内存碎片问题。在C/OS-II中使用内存控制块的数据结构来跟踪每一个内存分区,系统中的每个分区都有它自己的内存控制块。所有的内存控制块组成内存控制块链表,它在

9、C/OS-II初始化时建立。内存管理主要是由以下几个功能组成:建立内存分区、分配内存分区、释放内存分区、查询内存分区状态、使用内存分区、等待内存分区。4 C/OS-II任务调度4.1 C/OS-II的任务4.1.1任务及其任务状态任务,也称线程,是一个简单的应用程序,每个任务都是被赋予一定的优先级,并有自己的一套CPU寄存器和栈空间。实时应用程序的设计过程是如何把问题分割成多个任务。每个任务都是一个无限的循环,都处在一下五种状态之一,即休眠态,就绪态,运行态,挂起态和被中断态。1) 休眠态:相当于任务驻留在内存中,但并不能被多任务内核所调度;2) 就绪态:意味着任务已经准备好,可以运行,但是由

10、于该任务的优先级比正在运行的任务的优先级低,还暂时不能运行;3) 运行态:指任务掌握了CPU的使用权,正在运行中;4) 挂起太:指任务在等待,等待某一事件的发生;5) 被中断态:指发生中断时,CPU提供相应的中断服务,原来正在运行的任务暂时不能运行,就进入了中断态。4.1.2任务控制块(OS_TCB) 任务控制块是一个和任务息息相关的重要的结构体。当任务的CPU使用权被剥夺时,C/OS-I用它来保存该任务的状态。当任务重新获得CPU的使用权时,任务控制块能确保任务从被中断的那一点丝毫不差的继续执行。每个任务都拥有自己独立的任务控制块,一旦任务建立,与之相对应的任务控制块就被赋值。 任务控制块结

11、构体在C/OS-II中定义,以下代码是节选OS_TCB中对本文分析相关的结构体成员。/File: C/OS-II.HTypedef struts os_tcbOS_STK OSTCBStkPtr;.INT8U OSTCBPrio;INT8U OSTCBX;INT8U OSTCBY;INT8U OSTCBBitX;INT8U OSTCBBitY;.OS_TCB; OSTCBStkPtr是当前任务的栈顶指针,每个任务都有自己的堆栈和指向栈顶指针。在上下文切换时,对于优先级的任务,要将任务当前状态保存于任务堆栈中(以便以后再次调度到此任务继续执行),然后OSTCBStkPtr指向栈顶;对于优先级高的

12、任务,通过OSTCBStrPtr找到任务的上次被切换是的状态,把保存的状态恢复到CPU,这样任务就毫无差错的继续执行。 OSTCBPrio是任务的优先级号。OSTCBX,OSTCBBitX,OSTCBY,OSTCBBitY用于加速任务进入就绪态的过程或等待事件发生状态的过程,这些值在任务建立时调用OS_TCBInit进行赋值。4.2 C/OS-II最高优先级查找算法在C/OS-II中,每个就绪的任务都是放在就绪表(ready list)中,内核通过就绪表找到就绪太最高优先级的任务让其占用CPU,进入运行态。C/OS-II中最多运行任务是64哥,内核把任务优先级分组,八个为一组,如图1所示。任务

13、优先级号中Y 是所属组部分,X 是所在组部分,在就绪表中有2 个变量OSRdyGrp和OSRdyTbl ,OSRdyGrp 表示所属组,每一位代表一个组内是否有进入就绪态的任务,OSRdyTbl 表示所在组,一组八个任务,即一位代表一个任务是否进入就绪态。当任务进入就绪态时,就绪表OSRdyGrp 和OSRdyTbl 相应位置1。OSRdyGrp 和OSRdyTbl 之间的关系见图1,OSRdyGrp 的第n 位对应OSRdyTbl n ,即OSRdyTbl n 中任何一位是1时,OSRdyGrp 的第n 位要置1。 任务创建成功后被置于就绪态,这里就以任务被创建时为例来说明内核是如何把任务置

14、于就绪态。首先,建立任务,调用函数OSTaskCreat( )或OStaskCreatExt( ),OSTaskCreat( )和OStaskCreatExt( )都将调用OS_TCBInit( )来初始化任务控制块,函数OS_TCBInit( )完成将任务优先级放就绪表中,使任务置于就绪态,函数OS_TCBInit( )中有关将任务优先级放就绪表的部分如下所示/ File : OS_CORE.CINT8U OS_TCBInit(INT8U prio,.)OS_TCB* ptcb;/* 初始化OS_TCB 中OSTCBX,OSTCBBitX, OSTCBY,OSTCBBitY */ptcb-O

15、STCBY= prio 3;ptcb-OSTCBBitY = OSMapTblptcb-OSTCBY;ptcb-OSTCBX = prio & 0x07;ptcb-OSTCBBitX = OSMapTblptcb-OSTCBX;OSRdyGrp|= ptcb-OSTCBBitY; /* 将任务加入就绪表 */OSRdyTblptcb-OSTCBY |= ptcb-OSTCBBitX;OS_TCBInit( )对OSTCBX,OSTCBBitX, OSTCBY,OSTCBBitY 提前做了运算,节约任务调度时。OSTCBX 和OSTCBY 都要转换为相应位掩码,这个是通过OSMapTbl 实现,

16、如图2。内核通过按位或运算把OSRdyGrp 和OSRdyTbl 的相应位置1,这样就完成了把任务置于就绪态的工作。 图 2 OSMapTbl 所有任务置于就绪态的工作都是通过上面的两个或运算完成。最高优先级任务置于就绪态和查找就绪态最高优先级任务是相反的过程,通过把任务置于就绪态的分析知道了就绪表中是如何放置任务优先级信息的,接下来就要把最高优先级的任务从就绪表中查找出来。任务的优先级越高,任务的优先级号越小,在OSRdyGrp 和OSRdyTbl 中置1 的位越低,查找最高优先级的任务就是查出OSRdyGrp OSRdyTbl 和最低的置1 位,然后再转换为优先级号,这样就完成了最高优先级

17、的查找工作。内核调度任务时需要查找出最高优先级的任务。内核调用OS_Sched( )调度任务。OS_Sched( )找出就绪态最高OSPrioHighRdy,判断是否需要调度,如果需要则调度任务。函数OS_Sched( )中有关查找最高优先级的部分如下:/ File : OS_CORE.Cvoid OS_Sched (void)INT8U y;y = OSUnMapTblOSRdyGrp; /* 找出最高优先级 */OSPrioHighRdy = (INT8U)(y 3) + OSUnMapTblOSRdyTbly);为了找到就绪态的优先级最高的任务,内核并不是从OSRdyTbl 0 开始扫描

18、整个就绪任务表,只需查另外一张表即优先级判定表OSUnMapTbl ,如图3 所示,这样设计为内核调度节约了时间。优先级判定表OSUnMapTbl 中的值由OSRdyGrp 和OSRdyTbl 的最低置1 位确定,举例说明。假设OSRdyGrp0x6C(0b01101100),OSRdyGrp 的最后一位置1 是第2 位,OSUnMapTbl0x6C=2(图3 中红色标注部分),反过来,知道OSRdyGrp0x6C 就可以通过OSUnMapTbl0x6C找到2,这样通过OSUnMapTbl 把 OSRdyGrp 和OSRdyTbl 最低置1 位转换为对应优先级号中的Y 和X 部分,Y 乘以8

19、加上X 就是就绪任务的最小优先级号,即优先级最高的任务的优先级号,这样内核便完成了查找就绪态最高优先级任务的工作。 INT8U const OSUnMapTbl =0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0x00 to 0x0F4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0x10 to 0x1F5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0x20 to 0x2F4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,

20、 2, 0, 1, 0, /0x30 to 0x3F6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0x40 to 0x4F4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0x50 to 0x5F5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0x60 to 0x6F4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0x70 to 0x7F7, 0, 1, 0, 2, 0, 1, 0, 3, 0,

21、1, 0, 2, 0, 1, 0, /0x80 to 0x8F4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0x90 to 0x9F5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0xA0 to 0xAF4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0xB0 to 0xBF6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0xC0 to 0xCF4, 0, 1, 0, 2, 0, 1, 0, 3

22、, 0, 1, 0, 2, 0, 1, 0, /0xD0 to 0xDF5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /0xE0 to 0xEF4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /0xF0 to 0xFF;4.3 C /OS-任务调度原理C /OS-内核调用函数OS_Sched( )来完成任务调度。函数OS_Sched( )首先找出最高优先级任务的任务号,再与当前任务的任务号比较判断是否需要调度,如果两个任务号不相等则说明有更高优先级的任务进入就绪态需要进行任务调度,然后进入上下文切换

23、完成任务调度,反之则说明当前任务具有最高优先级,退出OS_Sched( )继续执行当前任务。有关内核源码如下:/ File : OS_CORE.Cvoid OS_Sched (void)INT8U y;.OS_ENTER_CRITICAL();if (OSIntNesting = 0) & (OSLockNesting = 0) y= OSUnMapTblOSRdyGrp; /* 查找最高优先级 */OSPrioHighRdy = (INT8U)(y OS_LOWEST_PRIO) (1) return (OS_PRIO_INVALID); OS_ENTER_CRITICAL(); if (O

24、STCBPrioTblprio = (OS_TCB *)0) (2) OSTCBPrioTblprio = (OS_TCB *)1; (3) OS_EXIT_CRITICAL(); (4) psp = (void *)OSTaskStkInit(task, pdata, ptos, 0); (5) err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); (6) if (err = OS_NO_ERR) (7) OS_ENTER_CRITICAL(); OSTaskCtr+; (8) OSTaskCreateHook(OSTCBPri

25、oTblprio); (9) OS_EXIT_CRITICAL(); if (OSRunning) (10) OSSched(); (11) else OS_ENTER_CRITICAL(); OSTCBPrioTblprio = (OS_TCB *)0; (12) OS_EXIT_CRITICAL(); return (err); else OS_EXIT_CRITICAL(); return (OS_PRIO_EXIST); 挂起任务,OSTaskSuspend()有时候将任务挂起是很有用的。挂起任务可通过调用OSTaskSuspend()函数来完成。被挂起的任务只能通过调用OSTaskR

26、esume()函数来恢复。任务挂起是一个附加功能。也就是说,如果任务在被挂起的同时也在等待延时的期满,那么,挂起操作需要被取消,而任务继恢复任务,OSTaskResume()在上一节中曾提到过,被挂起的任务只有通过调用OSTaskResume()才能恢复。OSTaskResume()函数的代码如程序清单 L4.17所示。因为OSTaskSuspend()不能挂起空闲任务,所以必须得确认用户的应用程序不是在恢复空闲任务L4.17(1)。注意,这个测试也可以确保用户不是在恢复优先级为OS_PRIO_SELF的任务(OS_PRIO_SELF被定义为0xFF,它总是比OS_LOWEST_PRIO大)。

27、续等待延时期满,并转入就绪状态。任务可以挂起自己或者其它任务。获得有关任务的信息,OSTaskQuery()用户的应用程序可以通过调用OSTaskQuery()来获得自身或其它应用任务的信息。实际上,OSTaskQuery()获得的是对应任务的OS_TCB中内容的拷贝。用户能访问的OS_TCB的数据域的多少决定于用户的应用程序的配置(参看OS_CFG.H)。由于C/OS-是可裁剪的,它只包括那些用户的应用程序所要求的属性和功能。改变任务的优先级,OSTaskChangePrio()在用户建立任务的时候会分配给任务一个优先级。在程序运行期间,用户可以通过调用OSTaskChangePrio()来

28、改变任务的优先级。换句话说,就是C/OS-允许用户动态的改变任务的优先级。5.4 实验步骤 5.4.1准备实验环境先在C盘上建一个名称为bc31的目录,然后到互联网上下载一个Borland C+3.1并安装到目录bc31中(因为书中的代码是用Borland C+3.1编译的),接着再把实验程序文件夹Software复制到C盘上。BC31实验环境的建立步骤如下: 5.4.2 编写源程序源程序 1#include includes.h#define TASK_STK_SIZE 512/任务堆栈长度OS_STK MyTaskStkTASK_STK_SIZE;/定义任务堆栈区OS_STK YouTas

29、kStkTASK_STK_SIZE;/定义任务堆栈区OS_STK HisTaskStkTASK_STK_SIZE;/定义任务堆栈区INT16S key;/用于退出uCOS_II的键INT8U x=0,y=0;/字符显示位置INT8U time=0;void MyTask(void *data);/声明任务void YouTask(void *data);/声明任务void HisTask(void *data);/*主函数*/void main (void) char* s_M=M;/定义要显示的字符 OSInit();/初始化uCOS_II PC_DOSSaveReturn();/保存Dos

30、环境 PC_VectSet(uCOS, OSCtxSw);/安装uCOS_II中断 OSTaskCreate(MyTask,/创建任务MyTasks_M,/给任务传递参数&MyTaskStkTASK_STK_SIZE - 1,/设置任务堆栈栈顶指针0);/使任务MyTask的优先级别为0 OSStart();/启动uCOS_II的多任务管理/*任务MyTask*/void MyTask (void *pdata) char* s_Y=Y;/定义要显示的字符#if OS_CRITICAL_METHOD = 3 OS_CPU_SR cpu_sr;#endif pdata = pdata; OS_E

31、NTER_CRITICAL(); PC_VectSet(0x08, OSTickISR);/安装uCOS_II时钟中断向量 PC_SetTickRate(OS_TICKS_PER_SEC);/设置uCOS_II时钟频率 OS_EXIT_CRITICAL(); OSStatInit();/初始化uCOS_II的统计任务 OSTaskCreate(YouTask,/创建任务MyTasks_Y,/给任务传递参数&YouTaskStkTASK_STK_SIZE - 1,/设置任务堆栈栈顶指针2);/使任务MyTask的优先级别为2 for (;) if (x50) x=0; y+=2; PC_Disp

32、Char(x, y,/显示字符的位置*(char*)pdata, DISP_BGND_BLACK+DISP_FGND_RED ); x += 1; /如果按下Esc键则退出uCOS_IIif (PC_GetKey(&key) = TRUE) if (key = 0x1B) PC_DOSReturn(); OSTimeDlyHMSM(0, 0, 2, 0);/等待 void YouTask (void *pdata) char* s_Y=H;/定义要显示的字符 OSTaskCreate(HisTask,/创建任务MyTasks_Y,/给任务传递参数&HisTaskStkTASK_STK_SIZE

33、 - 1,/设置任务堆栈栈顶指针3);/使任务MyTask的优先级别为0 for (;) if (x50) x=0; y+=2; PC_DispChar(x, y,/显示字符的位置*(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE ); x += 1; /如果按下Esc键则退出uCOS_IIif (PC_GetKey(&key) = TRUE) if (key = 0x1B) PC_DOSReturn(); OSTimeDlyHMSM(0, 0, 4, 0);/等待 /*任务YouTask*/void HisTask (void *pdata) char* s_Y=G;/定义要显示的字符 OSTaskCreate(MyTask,/创建任务MyTasks_Y,/给任务传递参数&MyTaskStkTASK_STK_SIZE - 1,/设置任务堆栈栈顶指针4);/使任务MyTask的优先级别为4 for (;) if (x50) x=0; y+=2; PC_DispChar(x, y,/显示字符的位置*(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE ); x += 1;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公文档 > 其他范文


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号