全部博文(86)
分类: 嵌入式
2017-11-19 22:48:45
任务管理机制
任务状态
任务的5中基本状态有休眠(dormant)、就绪(ready),运行(run),等待(pending)和中断(interrupted)状态。但是在给定的时刻只能是其中一种状态。任务状态转换图如下:
(1)、休眠状态是驻留在内存中的任务,但没有被uC/OS-III内核管理。通过调用OSTaskCreate()函数,可以把任务加入到uC/OS-III内核进行管理。当不再需要内核管理某个任务时,可以调用OSTaskDel()函数来删除。其实并不是真的删掉,只是被从内核管理中移除。
(2)、当一个任务准备运行时,它就是处于就绪状态。所有处于就绪状态的任务根据优先级被排放在就绪列表中。
(3)、就绪列表中最重要的任务会被执行,进入运行状态。一个CPU上,在任何时候只能运行一个任务。调用OSStart()、OSIntExit()和OS_TASK_SW()时,uC/OS-III会把最重要的就绪任务放到CPU上运行。当任务调用会使其进入挂起状态的函数来等待事件时,如果事件还没有发生,该任务就会进入等待状态。
(4)、处于等待状态的任务会被放到一个与该任务所等待的事件相对应的等待列表(pend-list)中。任务在等待事件发生过程中并不消耗CPU。当任务等待的事件发生时,任务会被放到就绪列表中。如果该任务的优先级比处于运行状态的任务高,该任务立即被运行,运行状态的任务会被放到就绪列表。
注意,调用OSTaskSuspend()的使任会无条件进入等待状态,只能另外一个任务调OSTaskResume()才能使该任务进入就绪状态。
(5)、如果中断被使能了,中断发生时,运行状态的任务会被挂起,CPU开始运行中断服务子程序ISR。ISR的工作要尽可能的少,通常是调用“Post”这类类函数(OSFlagPost(), OSQPost(),
OSSemPost(), OSTaskQPost(), OSTaskSemPost(),OSMutexPost()除外)通知在uC/OS-III管理中的任务去做中断处理的大部分工作。一个中断可以被另一个中断打断,叫做中断嵌套。大部分处理器都支持中断嵌套。如果管理不好,中断嵌套很容易导致堆栈溢出。
在uC/OS-III内部任务状态机中,一个任务状态可以处于下图中的8中状态之一。任务状态保存在TCB的成员中的一个变量。注意,在上图中并没有记录休眠状态的任务,因为uC/OS-III并不知道休眠状态的任务。中断和中断嵌套的跟踪方式与这个不同,会在后文讲解。这张状态转换图对于理解如何使用服务函数和它们对任务状态的影响有很大的帮助。强烈建议读者标记出这张框图。
(0)、绪状态的任务是状态0。这是任务实现其功能的唯一途径。
(1)、任务可以调用OSTimeDly()或者OSTimeDlyHMSM()让自己延时一段时间。当延时结束或者延时被取消时,任务又返回就绪状态。
(2)、任务可以调用某个pend函数(OSFlagPend(), OSMutexPend(), OSQPend(), OSSemPend(), OSTaskQPend(), OSTaskSemPend())等待某个时间的发生。当等待的时间发生了(也就是说,某个任务或者ISR执行了相对应的“post”函数),等待对象被删除,或者另外一个任务决定终止该等待时,该等待过程才会结束。
(3)、任务可以在指定的时间内等待时间的发生,如果在指定的时间内等待的事件没有发生,任务又返回到就绪状态,并且该任务会被通知等待超时了。同样,当等待的时间发生了(也就是说,某个任务或者ISR执行了相对应的“post”函数),等待对象被删除,或者另外一个任务决定终止该等待时,该等待过程才会结束。
(4)、一个任务可以调用OSTaskSuspend()使自己或者其他任务挂起。调用OSTaskResume()是使挂起的任务恢复运行的唯一方法。被挂起的任务在被恢复前失去CPU的使用权。如果一个任务把自己挂起,必须由其他任务来唤醒。
(5)、一个处于延时状态的任务可以被另其他任务挂起。这种情况下,只有延时结束(或者调用OSTimeDlyResume()取消延时),并且挂起被取消(被另外一个任务调用OSTaskResume()),该任务才能再次运行。
(6)、一个等待事件发生的任务可能被其他任务挂起。这种情况下,等待结束并且挂起被移除了,任务才能再次运行。
(7)、在一定时间内等待事件发生的任务可能被其他任务挂起。同样,挂起被移除并且等待的时间发生或者超时了任务才能再次运行。