来自Colin Walls的关于RTOS的全部真相。 第3条 任务与计划



我们研究了多任务处理,这是操作系统的属性,可以同时运行多个准独立程序。 在仔细研究任务之前,我们需要处理这些条款。

该系列中的先前文章:
第2条。 RTOS:结构和实时模式
第1条 RTOS:简介。

我们使用“任务”一词,尽管它没有确切的含义。 其他术语“流程”和“过程”则更为专业,您应该了解它们的含义以及它们之间的区别。

嵌入式应用程序中使用的许多RTOS都使用多线程模型。 可以同时执行多个线程,占用相同的地址空间:



这意味着上下文切换首先是从一组处理器寄存器切换到另一组。 简单,快速。 潜在的危险是,每个线程都有能力访问属于其他线程或RTOS本身的内存。

另一种选择是多进程模型。 如果正在运行多个进程,则每个进程都有其自己的地址空间,并且您无法访问与其他进程或RTOS相关的内存:



由于操作系统必须适当配置内存管理单元即内存管理器(英文内存管理单元,MMU),因此这使上下文切换更加困难和耗时。 当然,只有使用支持MMU的处理器,这种架构才有可能。 “高性能” RTOS和大多数桌面OS支持这些过程。 而且,每个进程都可以支持拆分为多个线程,但是在普通的嵌入式应用程序中很少使用此属性。

如果有MMU,则可以达成妥协:



许多“流式” RTOS支持MMU,以保护内存免受未经授权的访问。 因此,当任务处于上下文中时,仅其代码/数据的一部分以及RTOS的必要部分是“可见的”。 剩余的内存块被禁用,访问尝试将导致紧急情况(对于普通人)/异常(对于程序员)。 这使上下文切换更加困难,但是应用程序本身更加安全。 此模式可以称为“线程保护模式”或“轻量级进程模式”。

策划者



众所周知,通过分配处理器时间来完成每个任务,可以同时执行任务。 这是内核的核心功能。 在任务之间分配时间的方法称为“计划”。 计划程序—确定将控制权转移到的下一个任务的软件。 调度程序的逻辑以及确定何时应执行什么操作的机制是规划算法。 在本节中,我们将介绍几种计划算法。 任务计划是一个广泛的主题,许多书籍专门针对它。 我们将提供必要的最低限度,以了解特定RTOS在这方面可以提供的内容。

运行完成计划程序(RTC)



RTC调度程序(运行至完成)非常简单,并且占用最少的资源。 如果满足应用程序要求,这是一项理想的服务。 下面是使用RTC调度程序的系统的图形:



调度程序轮流调用每个任务的顶级功能。 该任务控制处理器(中断处理器),直到顶级函数执行return语句return为止。 如果RTOS支持任务的挂起,那么当前挂起的任何任务都不会执行。 在下面的文章中讨论了该主题,请参阅“暂停任务”。

除了简单之外,RTC调度程序的一大优势是代码的单个堆栈和可移植性(不需要汇编)。 缺点是任务可以“占用”处理器,因此需要仔细开发程序。 尽管事实上每次都从头开始执行任务(与其他调度程序不同,它允许您从停止位置开始工作),但您可以借助“状态”的静态变量来获得更大的灵活性,该变量确定每个后续调用的逻辑。

调度程序循环(RR)



RR调度程序(“轮播”)类似于RTC,但是更加灵活,因此更加复杂:



但是,对于RR调度程序,该任务不需要执行顶级函数中的return语句。 她可以随时通过调用RTOS来释放处理器。 此调用使内核保存当前任务的上下文(所有寄存器,包括堆栈指针和命令指针)并在队列中加载下一个任务的上下文。 在某些RTOS中,可以在预期内核资源可用的情况下释放处理器(暂停任务)。 这比较复杂,但是原理是相同的。

RR调度程序的灵活性取决于从暂停时刻起就可以继续执行任务而无需更改应用程序代码的能力。 为了灵活性,您必须减少代码的可移植性,并为每个任务支付单独的堆栈。

时间片调度程序(TS)



调度程序TS(时间片-“时间片”)比RR复杂。 时间分为几个时隙(时间间隔,时间片),每个任务都可以在指定的时间间隔内执行:



除了能够自动释放处理器的功能之外,还可以通过调用系统计时器中断处理程序执行的调度程序来中断任务。 为每个任务分配固定时间段的想法非常有吸引力(在可能的情况下):它易于理解,并且非常可预测。
TS调度程序的缺点是,为每个任务分配的CPU时间百分比可能会有所不同,这取决于其他任务是否被挂起以及插槽的其他部分是否空闲:



如果在后台执行任务,则TS调度程序可以变得更加可预测。 可以执行后台任务而不是任何挂起的任务,并占用任务释放(或暂停自身)的时间间隔。



显然,后台任务不应执行时间紧迫的工作,因为分配给它的处理器时间份额绝对是不可预测的:永远无法计划。

这种解决方案假定每个任务都可以预测何时重新计划。 例如,如果您有10 ms的插槽和10个任务,则该任务知道如果释放了该任务,它将在100 ms后继续执行。 使用此解决方案,您可以为应用程序任务实现更灵活的时间周期(定时)配置。
RTOS可以为每个任务提供不同的时隙。 这提供了更大的灵活性,但也像固定间隔大小一样可预测。 如果您需要增加分配的处理器时间的比例,则另一种选择是为同一任务分配多个时间间隔。

优先调度器



大多数RTOS支持基于优先级的计划。 这个想法很简单:每个任务都被赋予优先级,并且在任何时候,具有最高优先级并且“准备就绪”可以执行的任务都被转移到处理器:



当发生事件(例如,中断或对特定内核服务的调用)时,调度程序将启动,该事件会迫使具有高优先级的任务变为“就绪”状态。 调度程序在三种情况下开始工作:
•任务被挂起; 调度程序必须调度下一个任务。
•任务准备优先级更高的任务(使用API​​调用)。
•中断处理程序(Interrupt Service Routine,ISR)准备更高优先级的任务。 这可以是I / O设备的中断处理程序,也可以是系统计时器的结果。
优先级的数量有所不同(从8到几百个),阈值也有所不同:某些RTOS认为最高优先级为0,而另一些RTOS则认为最低优先级。
某些RTOS在每个优先级上只允许一项任务。 其他则允许一些,这极大地增加了相关数据结构的复杂度。 许多操作系统允许您在运行时更改任务的优先级,这使流程更加复杂。

复合调度程序



我们检查了几位计划者,但是,许多商业RTOS提供了更复杂的解决方案,这些解决方案具有多种算法的特征。 例如,RTOS可以在每个优先级上支持多个任务,然后使用TS在最高级别的几个现成任务之间分配时间。

任务状态



在任何给定时间,仅执行一项任务。 除了在中断处理程序(在下一篇文章中有更多介绍)或调度程序上花费的处理器时间之外,“当前”任务是当前正在执行其代码并且其数据由当前寄存器值表征的任务。 可能还有其他准备“启动”的任务,调度程序将考虑这些任务。 在使用RTC,RR或TS调度程序的简单RTOS中,仅此而已。 但是,更常见的是,在优先级调度程序中,任务也始终处于挂起状态,这意味着调度程序直到恢复它们并进入“就绪”状态时才考虑它们。

暂停任务



暂停任务非常简单:该任务自行暂停(通过调用API)或另一个任务将其暂停。 通过另一个API调用,可以由另一个任务或中断处理程序恢复挂起的任务。 这是“无条件”或“纯”暂停。 一些操作系统将此任务称为“睡眠”。

RTOS可以使任务暂停(入睡)一定时间,然后恢复(根据系统时钟)。 这可以称为“入睡”。

如果RTOS支持“阻止” API调用,则可以使用更复杂的暂停。 这样的调用允许任务请求服务或资源(如果可用),该服务或资源将立即接收。 否则,它将被挂起直到可用。 如果资源在特定时间段内不可用,也可以定义超时,任务将在该超时时继续执行。

其他任务状态



许多RTOS支持其他状态,但是概念和定义相​​差很大。 例如,状态为“完成”,这仅表示任务的外部功能已退出(通过返回代码或仅通过完成外部功能块)。 为了使已完成的任务重新开始运行,可能需要以某种方式将其重置。

另一种选择是终止状态。 这类似于完全暂停(纯操作),不同之处在于必须重置任务才能重新启动。

如果RTOS支持动态创建和删除任务(请参阅以下文章),则意味着任务的另一种可能状态-“已删除”。

当我们开发自己的实时OSRV MAX操作系统时(此前已发表过有关此文章的文章),我们的团队“遇到了” Mentor Graphics的微电子学和固件专家Colin Walls的博客。 文章似乎很有趣,可以自己翻译,但是为了不“写到桌子上”,他们决定发表文章。 希望它们对您也有用。 如果是这样,那么我们计划发布该系列中所有翻译的文章。

关于作者: Colin Walls在电子行业工作了30多年,大部分时间用于固件。 他现在是Mentor Embedded(Mentor Graphics的一个部门)的固件工程师。 Colin Walls经常在会议和研讨会上发表演讲,他撰写了许多技术文章并撰写了两本有关固件的书。 居住在英国。 Colin的专业博客: blogs.mentor.com/colinwalls ,电子邮件:colin_walls@mentor.com

该周期的第一篇和第二篇文章都张贴在这里。

Source: https://habr.com/ru/post/zh-CN415329/


All Articles