到目前为止,创建的任务一直都有进行处理,从来没有必要等待任何事情,因为它们不必等待任何东西,它们总是能够进入运行状态。这种“连续处理”任务的有用性有限,因为它们只能以最低优先级创建。如果它们以任何其他优先级运行,它们将防止优先级更低的任务完全运行。
为了使任务变得有用,它们必须重写为事件驱动。事件驱动的任务只有在触发事件的事件发生后才能执行(处理),并且在该事件发生之前不能进入运行状态。调度程序总是选择能够运行的最高优先级任务。高优先级任务无法运行意味着调度程序不能选择它们,而是选择能够运行的较低优先级的任务。因此,使用事件驱动的任务意味着可以以不同的优先级创建任务,而没有最高优先级的任务使处理时间的所有较低优先级任务变得饥饿。
阻塞状态(Block)
正在等待事件的任务被称为处于“已阻止”状态,这是“不运行”状态的子状态。
任务可以进入阻止状态等待两种不同类型的事件:
- 时间(时间相关)事件 - 事件是延迟期到期或绝对时间到达。例如,任务可能进入阻塞状态等待10毫秒。
- 同步事件 - 事件来自另一个任务或中断。例如,任务可以进入阻塞状态以等待数据到达队列。同步事件涵盖广泛的事件类型。
一个任务可以用一个超时来阻止同步事件,同时有效地阻止这两种类型的事件。例如,任务可以选择等待最多10毫秒的数据到达队列。如果任何一个数据在10毫秒内到达,或10毫秒内没有数据到达,任务将离开阻塞状态。
暂停、挂起(Suspended)
“暂停”也是不运行的子状态。 挂起状态的任务对调度程序不可用。 进入暂停状态的唯一方法是通过调用vTaskSuspend()API函数,离开暂停状态的唯一方法是通过调用vTaskResume()或xTaskResumeFromISR()API函数。 大多数应用程序不使用暂停状态。
就绪(Ready)
处于非运行状态但未被阻止或暂停的任务据说处于就绪状态。 他们能够运行,处于“准备”运行,但目前不处于运行状态。状态转换图
图15展开了先前的过度简化状态图,以包括本节中描述的所有不运行子状态。 迄今为止在示例中创建的任务没有使用被阻止或已暂停的状态; 它们只在就绪状态和运行状态之间进行转换 - 由图15中的粗线突出显示。