我正在阅读David E.Simon的"嵌入式软件底漆"。在其中讨论了RTO及其基础调度程序和任务。它说每个任务都处于现成状态,运行状态或阻止状态。我的问题是调度程序如何确定任务是在阻止状态下的?假设它正在等待信号量。然后,它可能处于无法返回的状态。调度程序是否查看函数是否不返回,然后将其状态标记为阻塞?
实现详细信息将因RTO而异。通常,每个任务都有一个状态变量,可以标识任务是否准备就绪,运行或阻止。调度程序只需读取任务的状态变量即可确定是否阻止任务。
每个任务都有一组参数,可以确定任务的状态和上下文。这些参数通常存储在结构中,并称为"任务控制块"(尽管实现因RTO而变化)。Ready/Run/Block状态变量可以是任务控制块的一部分。
当任务尝试获取信号量并且信号量不可用时,该任务将设置为阻塞状态。更具体地说,Semaphore-get函数将将任务从运行更改为阻塞。然后调用调度程序以确定下一个任务应运行。调度程序将仔细阅读任务状态变量,并且不会运行那些被阻止的任务。
当另一个任务最终设置了信号量时,将从封锁到准备状态,并可以调用调度程序以确定是否应发生上下文开关。
当我写rtos(http://distortos.org/)时,我以为我可能会在。
持有每个线程状态的变量确实通常在rtoses中实现,其中包括矿山版本:https://github.com/distortec/distortos/blob/master/include/distortos/threadstate.hpp#l26https://github.com/distortec/distortos/blob/master/include/include/distortos/internal/scheduler/threadcontrolblock.hpp#l329
但是,此变量通常仅作为调试辅助工具或进行其他检查(例如阻止您启动已经启动的线程)。
在针对深入嵌入系统的RTOSE中,通常使用固定螺纹的容器进行准备/阻塞之间的区别。通常,线程在链接列表中"链接",通常也按优先级和插入时间进行排序。调度程序有自己的"准备就绪"的线程列表(https://github.com/distortec/distortec/distortos/blob/master/master/include/distortos/internal/internal/scheduler/scheduler/scheduler.hpp#l340)。每个同步对象(如信号量)也都有其自己的线程列表,这些线程被"阻止"等待此对象(https://github.com/distortec/distortec/distortec/distortos/blob/blob/master/master/include/include/distortos/semaphore.hpp#l244)。当线程尝试使用当前尚不可用的信号量时,它只是将其简单地从调度程序的"就绪"列表中移动到Semaphores的" blocked"列表(https://github.com/distortec/distortec/distortec/distortec/distortos/blob/master/master/source/,同步/信号量。CPP#l82)。调度程序不需要决定任何事情,因为从调度程序的角度来看 - 此线程刚刚消失。当该信号量现在由另一个线程发布时,在此信号量的"阻止"列表上等待的第一个线程将移回调度程序的" Ready"列表(https://github.com/distortec/distortec/distortec/distortos/distortos/blob/master/master/master/source/,Synchronization/Smaphore.cpp#l39)。
通常,无需在准备就绪的线程和实际运行的线程之间进行特殊区分。由于实际运行的线程数量是固定的,并且等于可用CPU内核的数量,因此您需要的只是每个CPU核心的指针,该指针指向" Ready"列表的线程那一刻。在我的系统中,我也这样做 - "就绪"列表的头部的线程是正在运行的线程,但是我也管理一个指向该线程的迭代器(https://github.com/distortec/distotos/blob/master/includ/distortos/internal/scheduler/scheduler.hpp#l337)。您可能有一个单独的跑步线程列表,但是在大多数情况下,它会浪费空间(通常只有一个),并且使其他事情变得更加复杂。
我实际上写了一篇有关线程状态及其过渡的文章-http://distortos.org/documentation/task-states/本文在"准备就绪"的线程之间没有特殊的区别和实际运行的那个。我认为这种区别实际上对任何事物都是有用的,只要您有其他方法可以判断哪个"就绪"线程正在运行。