您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > 54时间片轮询多任务操作系统
5.4时间片轮询多任务操作系统目录1概述2整体规划3任务控制块4内部变量初始化5创建任务6启动多任务环境longjmpInIsr()9任务调度7时钟节拍中断8任务延时10删除任务11运行的任务难以得知其他任务状态,任务切换时机难以把握。如果一个任务死掉,势必造成整个系统死掉。协作式多任务系统任务协作式多任务系统的特点安全性复杂性协作式多任务系统中,任务切换需正在运行的任务主动让出CPU,这不仅带来一些安全隐患,而且使程序设计相当的复杂。任务调度任务调度交给操作系统,引入调度算法调度算法时间片轮询1优先级调度2带优先级调度的时间片轮询3调度算法时间片轮询1tt任务的运行时间时间片轮询系统中任务运行情况在时间片轮询操作系统中,CPU的执行时间被划分为若干时间片,然后让处于就绪状态的任务,按顺序轮流占用CPU。当时间片用完时,即使任务未执行完,系统也剥夺此任务的CPU使用权力。时间片长度Δt一般为1~10ms优先级调度2带优先级调度的时间片轮询3任务A任务B任务C所有任务相同对待,分时运行。调度算法时间片轮询1优先级调度2带优先级调度的时间片轮询3+低优先级+中优先级+高优先级任务A任务B任务Ct高优先级任务先运行t高优先级任务抢占低优先级任务不同任务不同对待,优先级高任务的先运行。调度算法时间片轮询1优先级调度2带优先级调度的时间片轮询3这种调度算法情况较复杂,类型较多,自己去学习了解。任务切换时机分配给任务的时间片已到任务主动请求调度12任务在调用操作系统提供的“管理”类服务(如删除任务等)和“等待”类服务(如延时、获取信号量、等待消息等)时,会主动请求调度。操作系统采用一个周期性的中断来管理时间片,在这个中断服务函数中,判断运行的任务是否用完了时间片。使用时间片轮询调度的操作系统中,会在两种下进行任务切换。目录2整体规划1概述34任务控制块内部变量初始化时间片轮询操作系统规划时间片轮询调度算法时间片轮询多任务操作系统协作式多任务系统TinyOS51V1.0TinyOS51V1.1TinyOS51V1.1采用最简单的时间片轮询调度算法,在每个时钟节拍中断时调度,即分配给任务的时间片为一个时钟节拍。这样,在任务控制块中不仅不需要保存时钟任务剩余的时钟节拍,而且也不必编写计算任务的剩余时间和设置任务时间片的代码。TinyOS51从V1.0到V1.1的改变TinyOS51V1.0TinyOS51v1.1任务调度函数tnOsSched()__tnOsSched()任务延时函数无tnOsTimeDly()时钟节拍处理函数无tnOsTimeTick()TinyOS51V1.0和TinyOS51V1.1的API不同点提供操作系统的一种基本服务——延时服务,延时以时钟节拍为单位。在TinyOS51中,时钟节拍中断由用户实现,在时钟节拍中断处理函数中调用tnOsTimeTick()。voidtask0(void){TMOD=(TMOD&0xF0)|0x01;TL0=0x00;//TH0=0x00;//初始化timer0,即TR0=1;//初始化时钟节拍ET0=1;//中断。TF0=0;//while(1){__GucTask0++;}}/**一个简单的任务,无限循环中让*__GucTask0++。*/voidtask1(void){while(1){__GucTask0++;}}/**用户实现时钟节拍中断服务函数,*并调用tnOsTimeTick()。*/voidtimer0ISR(void)__interrupt1{tnOsTimeTick();}/**1.初始化系统*2.创建任务*3.启动系统*/voidmain(void){tnOsInit();tnOsTaskCreate(task0,__GucTaskStks[0];tnOsTaskCreate(task1,__GucTaskStk[1]);tnOsStart();}资源配置与示例任务函数task0()和task1()时钟节拍中断服务函数timer0ISR()main函数main()staticidataunsignedchar__GucTaskStk[2][32];staticunsignedchar__GucTask0;staticunsignedchar__GucTask1;//分配任务堆栈//任务0测试变量//任务1测试变量全局变量定义函数实现目录3任务控制块45内部变量初始化创建任务12概述整体规划任务控制块TinyOS51V1.1增加了延时服务功能,因此,在TCB中增加了一个记录时间的成员uiTicks。#define__TN_TASK_FLG_DEL0x00//任务被删除#define__TN_TASK_FLG_RDY0x01//任务就绪#define__TN_TASK_FLG_DLY0x02//任务延时structtn_os_tcb{jmp_bufjbTaskContext;//任务上下文unsignedcharucTaskStat;//任务状态unsignedintuiTicks;//任务延时时间};typedefstructtn_os_tcbTN_OS_TCB;staticdataTN_OS_TCB__GtcbTasks[TN_OS_MAX_TASKS];//任务控制块数组与任务控制块相关代码:目录4内部变量初始化56创建任务启动多任务环境23整体规划任务控制块tnOsInit()voidtnOsInit(void){TN_OS_TASK_HANDLEthTask;//操作的任务for(thTask=0;thTaskTN_OS_MAX_TASKS;thTask++){__GtcbTasks[thTask].ucTaskStat=__TN_TASK_FLG_DEL;//任务初始处于删除状态__GtcbTasks[thTask].uiTicks=0;//设置初值}__GthTaskCur=0;//初始运行0号任务}由于TCB增加了一个uiTicks,则在tnOsInit()中进行初始化。OS初始化函数代码:目录5创建任务67启动多任务环境任务调度34任务控制块内部变量初始化通常,为了提高可移植性,采用一个宏或函数来编写实现开中断和关中断程序。由于TinyOS51仅适合80C51系列单片机,故直接使用“EA=0”和“EA=1”。创建任务函数tnOsTaskCreate()由于tnOsTaskCreate()要操作TCB,而时钟节拍中断中也要操作TCB,因此tnOsTaskCreate()中操作TCB的代码为临界区代码,要避免被时钟节拍中断打断。TinyOS51中采用开/关中断的方式解决此问题。TN_OS_TASK_HANDLEtnOsTaskCreate(void(*pfuncTask)(void),idataunsginedchar*pucStk){TN_OS_TASK_HANDLEthRt;for(thRt=0;thRtTN_OS_MAX_TASKS;thRt++){EA=0;//禁止中断if(__GtcbTasks[thRt].ucTaskStat==__TN_TASK_FLG_DEL){setTaskJmp(pfuncTask,pucStk,__GtcbTasks[thRt].jbTaskContext);__GtcbTask[thRt].ucTaskStat=__TN_TASK_FLG_RDY;EA=1;//允许中断returnthRt;}EA=1;//允许中断}目录6启动多任务环境78任务调度时钟节拍中断45内部变量初始化创建任务tnOsStart()在TinyOS51V1.1中,如果不允许中断,则时钟节拍中断服务程序不会运行,因此,在tnOsStart()中增加允许中断的代码。voidtnOsStart(void){EA=1;//允许中断longjmp(__GtcbTask[0].jbTaskContext);//执行0号任务}tnOsInit()中__GthTaskCur=0,即当前运行任务为0号任务。目录7任务调度89时钟节拍中断longjmpInIsr()56创建任务启动多任务环境__tnOsSched()tnOsSched()开/关中断代码__tnOsSched()TinyOS51V1.0TinyOS51V1.1任务调度函数__tnOsSched()中也要操作TCB,因此也需要加入开/关中断代码包含临界区。另外,__tnOsSched()不再提供给任务直接调用,仅供内部调用,因此添加前缀“__”。保护临界资源目录8时钟节拍中断9longjmpInIsr()任务延时67启动多任务环境任务调度10如果uiTicks不为0,则uiTicks--,即缩短延时时间。未使用任务状态标志判断任务是否处于延时状态。这是因为TinyOS51更高的版本具有超时功能,需要使用uiTicks来判断任务是否超时。如果uiTicks为0,则将任务设置为就绪状态。为了向上兼容超时代码,即区分系统服务是正常返回还是超时返回,未直接将任务设置为就绪状态,而使用“|=”操作。时钟节拍中断大多数操作系统中的延时管理和中断服务程序中的任务切换功能,分别是用两个函数实现的,由于TinyOS51V1.1是纯粹的时间片轮询操作系统,非时钟节拍中断的中断服务程序不进行任务切换操作,因此将二者合二为一。for(thTask=0;thTaskTN_OS_MAX_TASKS;thTask++){if(__GtcbTasks[thTask].uiTicks!=0){__GtcbTasks[thTask].uiTicks--;//缩短延时时间if(__GtcbTasks[thTask].uiTicks==0){__GtcbTasks[thTask].ucTaskStat|=__TN_TASK_FLG_RDY;//设置任务就绪状态位}}}}延时管理1任务切换2对于80C51来说,规定:一般函数返回使用RET指令,而中断返回使用RETI指令。由于longjmp()函数是使用RET指令返回的,如果在时钟节拍中断中继线使用longjmp(),则任务切换后CPU会认为中断仍未退出,同级中断(包括自身)将被屏蔽,从而造成整个系统执行错误。因此必须将longjmp()函数改为longjmpInIsr()。时钟节拍中断大多数操作系统中的延时管理和中断服务程序中的任务切换功能,分别是用两个函数实现的,由于TinyOS51V1.1是纯粹的时间片轮询操作系统,非时钟节拍中断的中断服务程序不进行任务切换操作,因此将二者合二为一。for(thTask=0;thTaskTN_OS_MAX_TASKS;thTask++){thTmp2++;if(thTmp2=TN_OS_MAX_TASKS){thTmp2=0;}if((__GtcbTasks[thTmp2].ucTaskStat&__TN_TASK_FLG_RDY)!=0){cTmp1=setjump(__GtcbTask[__GthTaskCur].jbTaskContext);//保持上下文if(cTmep1==0){__GthTaskCur=thTmp2;longjmpInIsr(__GtcbTasks[thTmp2].jbTaskContext);//中断中切换上下文}}}延时管理1任务切换2目录9longjmpInIsr()任务延时删除任务78任务调度时钟节拍中断1110中断中切换任务在中断中切换任务,不能再使用longjmp(),因为中断需要使用专用返回指令RETI,非RET指令。charlongjmpInIsr(jmp_bufBuf)__naked{unsignedcharucSpSave;//用于保存堆栈指针的变量dataunsignedchar*pucBuf=(datavoid*)0;//指向上下文信息存储位置的指针pucBuf=(dataunsignedchar*)jbBuf;ucSpSave=*pucBuf++;bp=*pucB
本文标题:54时间片轮询多任务操作系统
链接地址:https://www.777doc.com/doc-722070 .html