做过单片机的,相比都用过51、STM32等等系列,当今比较主流的单片机以STM32系列的为主,当在用STM32单片机一段时间之后就会手痒痒去尝试使用一下操作系统,那么就一定会接触到uC/OS-II,说到uC/OS-II那么就一定会有任务这样的概念。
任务在创建后将从睡眠态转换到就绪态,就绪的任务如果调用OSTaskSuspend将被阻塞,也就是被剥夺CPU的使用权而暂时中止运行,转到阻塞状态。通过OSTaskSuspend将任务转到阻塞态被称为挂起任务。
被挂起的任务不能运行,知道其他任务以该任务的优先级作为参数调用OSTaskResume来恢复它,才能将该任务的状态重新设置为就绪状态。当该任务是就绪的高优先级的任务时,又可以得到调度而重新占领CPU,回到运行态。
一个任务如果无事可做,且优先级又较高,长期占有CPU,那么其他的任务将得不到运行而“饿死”。因此,任务在不需要运行的时候应该放弃CPU,挂起就是其中的一种策略,除此之外还有任务延时等策略。
由上图可知,在运行过程的任务因为调用OSTaskSuspend而被挂起到阻塞态。阻塞态的任务因为其他任务以该任务的优先级作为参数调用OSTaskResume而得到恢复,恢复到就绪态。就绪的任务在优先级变为高的情况下终得到了运行。
值得注意的是,挂起一个任务并非将其转换挂起态,而是阻塞态。任务因为中断失去CPU控制权才会转换为挂起态,挂起态的任务在中断结束后直接回到运行态。这两者是有明显的区别的。
函数OSTaskSuspend用来暂时停止一个任务的执行,将任务转换为阻塞态。如果传递给OSTaskSuspend的参数是OS_PRIO_SELF,则将阻塞自己,如果prio是其他任务的优先级,则将阻塞其他的就绪任务。
根据该函数执行过程中的各种情况,返回值包括:
OS_ERR_NONE:如果成功挂起一个任务
OS_ERR_TASK_SUSPEND_IDLE:如果试图阻塞空闲任务。
OS_ERR_PRIO_INVALID:非法的优先级
OS_ERR_TASK_SUSPEND_PRIO:要挂起的任务不存在
OS_ERR_TASK_NOT_EXITS:要挂起使用互斥信号量的任务。
另外有一点需要特别注意的是,如果挂起了一个任务,那么要注意这个任务是否在等待某些事件的发生,需要防止在事件发生的时候阻塞了的任务因为事件的发生而运行。
调用时要十分小心,如果你想挂起一个等待事件(邮箱,消息,队列)的任务,事件到来的时候你将阻止这个任务运行。
注意:OSTaskSuspend()需要与OSTaskResume()恢复挂起的任务成对使用