嵌入式开发,究竟何时需要用RTOS
发布时间:2023-12-18 14:36:36
如今,高性能处理器和通用操作系统实时升级的速度,似乎再次引发了嵌入式系统是否仍需要RTOS的讨论。答案没有改变:在相对低端的处理器上只有真正的RTOS能提供一些保障,也就意味着,这些OS可以留在嵌入式环境中。
■ 究竟何时需要实时操作系统?
大多数嵌入式项目是否仍需要实时操作系统?考虑到当今高性能处理器的速度以及适用于Linux,Windows和其他通用操作系统(GPOS)的实时补丁的可用性,这是一个很好的问题。
答案在于嵌入式设备的本质。这些设备通常以数千,甚至数百万桃这种规模下生产,即使每套硬件成本降低1美元,也能为制造商节省一笔小财富。换言之,这些设备无法负担数百万赫兹处理器的成本(更不用说散热了)。
例如,在汽车远程信息处理市场,典型的32位处理器的运行频率约为600兆赫,远低于台式机和服务器中常见的处理器。在这样的环境中,设计用于从低端硬件中提取极其快速、可预测的响应时间的实时操作系统有巨大的经济优势。
除了节省成本外,实时操作系统提供的服务使许多计算问题更容易解决,特别是当多个活动竞争一个系统的资源时。例如,考虑一个用户期望(或需要)立即响应输入的系统。使用实时操作系统,开发人员可以保证由用户发起的操作将优先于其他系统活动执行,除非必须首先执行更重要的活动(例如,有助于保护用户安全的操作)。
还要考虑一个必须满足服务质量(QoS)要求的系统,例如显示实时视频的设备。如果设备的内容交付的任何部分都依赖于软件,那么它会以用户认为不可接受的速度体验掉帧,设备是不可靠的。然而,通过实时操作系统,开发人员可以精确地控制软件进程的执行顺序,并确保以适当和一致的速率进行回放。
■ 实时操作系统不公平
在嵌入式行业中,对实时“硬”时间的需求仍然很普遍。问题是:实时操作系统有什么是GPOS没有的?而且,对于某些GPOS来说,现在的实时扩展有多有用?他们能提供一个合理的实时操作系统性能吗?
让我们从任务调度开始。在GPOS中,调度程序通常使用“公平”策略将线程和进程分派到CPU。这样的策略可以实现桌面和服务器应用程序所需的高整体吞吐量,但不能保证高优先级、时间紧迫的线程优先于低优先级的线程执行。
例如,GPOS可能会降低分配给高优先级线程的优先级,或者为了保证系统中其他线程的公平性而动态调整线程的优先级。因此,高优先级线程可能被低优先级线程抢占。此外大多数GPOS具有无界的调度延迟:系统中的线程越多,GPOS调度一个执行线程所需的时间就越长,这些因素中的任何一个都可能导致高优先级线程错过最后期限,即使是在高速CPU上。
此外,高优先级线程可以不间断地运行,直到它完成它需要做的事情,当然,除非它被一个更高优先级的线程抢占。这种方法被称为基于优先级的抢占式调度,允许高优先级线程满足其最后期限,即使许多其他线程正在争夺CPU时间。
■ 抢占式内核
在大多数GPOS中,os内核是不可抢占的。因此,高优先级用户线程永远不能抢占内核调用,而是必须等待整个调用完成—即使调用是由系统中优先级最低的进程调用的。此外,当驱动程序或其他系统服务(通常在内核调用中执行)代表客户端线程执行exe剪切时,所有优先级信息通常都会丢失。这种行为会导致不可预知的延迟,并阻止关键活动按时完成。
另一方面,在实时操作系统中,内核操作是可抢占的。与在GPOS中一样,在时间窗口中可能不会发生抢占,在设计良好的实时操作系统中,这些窗口非常短,通常是数百纳秒的顺序。此外,实时操作系统对抢占延迟和中断禁用的时间设置了一个上限;这个上限允许开发人员确定最坏情况下的延迟。
为了实现一致的可预测性和关键活动的及时完成这一目标,实时操作系统内核必须尽可能简单优雅。实现这种简单性的最佳方法是设计一个内核,该内核只包含具有短执行路径的服务。通过从内核中排除工作密集型操作(例如进程加载)并将其分配给外部进程或线程,实时操作系统设计器可以帮助确保通过内核的最长不可抢占代码路径上存在上限。
在一些GPOS中,内核增加了一定程度的抢占性。然而,不可能发生抢占的时间间隔仍然比典型实时操作系统中的时间间隔长得多;任何此类抢占时间间隔的长度将取决于GPOS内核中任何模块(例如,网络)的最长关键部分。此外,一个可抢占的GPOS内核不会处理其他可能造成无限延迟的条件,例如,当客户端调用驱动程序或其他系统服务时发生的优先级信息丢失。
■ 避免优先级反转
在GPOS中,甚至在实时操作系统中,低优先级线程可能无意中阻止高优先级线程访问cpu,这种情况称为优先级反转。当发生无限优先级反转时,可能会错过关键的最后期限,从而导致从异常系统行为到彻底失败的结果。不幸的是,在系统设计过程中,优先级反转常常被忽略。优先级反转的例子很多,其中包括1997年7月火星探险者项目。
一般来说,当两个不同优先级的任务共享一个资源,而高优先级的任务无法从低优先级的任务获得资源时,就会发生优先级反转。为了防止这种情况超过有限的时间间隔,实时操作系统可以提供GPOS中不可用的机制选择,包括优先级继承和优先级上限模拟。我们不可能公正地对待这两种机制,所以让我们关注一个优先级继承的例子。.
首先,我们必须考虑任务同步如何导致阻塞,以及阻塞如何反过来导致优先级反转。假设两个任务正在运行,任务1和任务2,并且任务1具有更高的优先级。如果任务1已准备好执行,但必须等待任务2完成活动,则会阻塞。此阻塞可能是由于同步造成的;例如,任务1和任务2共享由锁或信号量控制的资源,而任务1正在等待任务2解锁该资源。或者,可能是因为任务1正在请求任务2当前使用的服务。
阻塞允许任务2运行,直到发生任务1正在等待的条件(例如,任务2解锁两个任务共享的资源)。此时,任务1开始执行。任务1必须等待的总时间称为阻塞因子。如果任务1要满足其任何时间限制,则此阻塞因子不能随任何参数(例如线程数或系统输入)而变化。换句话说,阻塞因子必须是有界的。
现在让我们介绍第三个任务,任务 3,它的优先级高于任务 2,但低于任务 1(参见图1)。如果任务3在任务2执行时准备好运行,则它将抢占任务2,并且任务2将无法再次运行,直到任务3阻塞或完成。当然,这个新任务会增加任务1的阻塞因子;也就是说,它会进一步延迟任务1的执行。抢占引入的总延迟是一个优先级反转。
图2 任务2继承任务1的较高优先级,从而防止任务3抢占任务2。任务3不再延迟任务1的执行。
■ 分区调度器
对于许多系统,保证资源可用性是至关重要的。如果一个关键的子系统被剥夺了,比如说,CPU周期,那么这个子系统提供的服务对于用户来说就变得不可用了。例如,在拒绝服务(DoS)攻击中,恶意用户可以用需要高优先级进程处理的请求轰炸系统。这个进程可能会使CPU超载,使其他进程的CPU周期中断,从而使系统对用户不可用。
安全漏洞并不是进程饥饿的唯一原因。在许多情况下,向系统添加软件功能会将系统推向“崩溃的边缘”,并使现有的应用程序占用大量CPU时间。及时运行的应用程序或服务不再按预期或要求作出响应。从历史上看,解决这个问题的唯一办法要么是改造硬件,要么是重新编码(或重新设计)软件——两者都是不受欢迎的选择。为了解决这些问题,系统设计人员需要一个分区方案,通过硬件或软件强制执行CPU运算,以防止进程或线程独占其他进程或线程所需的CPU周期。由于实时操作系统已经提供了对CPU、内存和其他计算资源的集中访问,所以实时操作系统是执行CPU分区运算的最佳选择。
有些实时操作系统提供一个固定的分区调度器。使用此调度器,系统设计人员可以将任务划分为组或分区,并为每个分区分配一定百分比的CPU时间。使用这种方法,任何给定分区中的任务消耗的CPU时间都不会超过分区静态定义的百分比。例如,假设一个分区分配了30%的CPU。如果该分区中的进程随后成为拒绝服务攻击的目标,那么它消耗的CPU时间将不超过30%。这个分配的限制允许其他分区保持其可用性;例如,它可以确保用户界面(例如远程终端)保持可访问性。因此,操作员可以访问系统并解决问题,而不必按下复位开关。
然而,这种方法有一个问题。因为调度算法是固定的,所以一个分区永远不能使用分配给其他分区的CPU周期,即使这些分区没有使用它们分配的周期。这种方法会浪费CPU周期,并阻止系统处理峰值需求。因此,系统设计者必须使用更昂贵的处理器,容忍更慢的系统,或者限制系统能够支持的功能数量。
■ 自适应分区