多模式实时系统中的上限协议:问题与解决方案
在多模式实时系统中,资源共享和任务调度是一个复杂的问题。尤其是在固定优先级抢占式调度的实时系统中,模式的变化可能会导致优先级的临时反转,从而影响任务的可调度性。本文将探讨这个问题,并介绍两种解决方案。
问题的提出
在多模式实时系统中,同一资源在不同的操作模式下可能会有不同的上限优先级。当应用上限的上限(ceiling of ceilings)时,可能会导致任务优先级的临时反转,从而使低优先级任务不必要地阻塞高优先级任务,甚至导致任务错过截止日期。
例如,在模式 M1 中,任务 T3、T2 和 T1 的优先级分别为 3、2 和 1。假设存在一个受保护对象 PO,其上限优先级为 2。当根据公式(1)重新评估 PO 的上限优先级后,T2 和 T1 的最大优先级变为 4,而 T3 的最大优先级仍为 3。这意味着在运行时,T3 可能会因为 T2 或 T1 持有 PO 所代表的资源而被阻塞,从而错过其截止日期。
任务 | 应用公式(1)前最大优先级 | 应用公式(1)前优先级 | 应用公式(1)后最大优先级 | 应用公式(1)后优先级 |
---|---|---|---|---|
T3 | 3 | 3 | 3 | 3 |
T2 | 2 | 2 | 4 | 2 |
T1 | 2 | 1 | 4 | 1 |
第一种解决方案:重新分配任务优先级
为了避免上述例子中 T3 优先级的反转,我们可以为 T3 分配一个新的优先级,使其在模式 M1 中恢复相对于 T2 和 T1 的重要性。在这个例子中,新的优先级应该大于 4,我们可以将其设为 5,以恢复任务的原始优先级顺序。
任务 | 最大优先级 | 优先级 |
---|---|---|
T3 | 5 | 5 |
T2 | 4 | 2 |
T1 | 4 | 1 |
然而,在更一般的情况下,提高 T3 的优先级时需要谨慎,因为这可能会影响其他高优先级任务。例如,如果存在另一个任务 T5,其在模式 M1 中的优先级为 4,且不使用受保护对象,那么将 T3 的优先级提高 2 个单位会错误地使 T3 比 T5 更重要。为了避免这种情况,我们必须重新分配所有原始优先级高于 PO 在模式 M1 中原始上限的任务的优先级。如果我们将 T3 的优先级提高了 D 个单位(在这个例子中 D = 5 - 3 = 2),那么 T5 的新优先级应该为 4 + D = 6。
第一种解决方案的推广:重新缩放算法
重新缩放算法是一种系统地重新分配在不同操作模式下共享对象的任务优先级的方法。该算法的实现步骤如下:
1.
任务排序
:根据首选策略(速率单调或截止日期单调),按照周期或截止日期对每个模式下的任务集进行排序。尽管存在阻塞问题,但通过这种排序可以得到一个初始的优先级分配。
2.
确定优先级数值
:使用优先级重新缩放算法,为每个任务的优先级和对象的上限分配一个数值,以使系统在所有操作模式下都与规范保持一致。该算法会保留步骤 1 中的排序,但新的优先级数值将避免由于应用上限的上限而导致低优先级任务不必要地阻塞高优先级任务。
3.
计算响应时间
:按照相关文献中描述的方法,计算所有任务的响应时间。
4.
可调度性分析
:将每个任务的响应时间与其截止日期进行比较,以确定在最坏情况下任务是否能够在截止日期内响应。
graph TD;
A[任务排序] --> B[确定优先级数值];
B --> C[计算响应时间];
C --> D[可调度性分析];
重新缩放算法的伪代码如下:
计算每个对象的最大上限优先级,应用公式(1)
循环
Modified := False
对于每个操作模式 M 循环
对于每个对象 Obj(按最大上限优先级降序排列)循环
如果 Obj 的最大上限大于模式 M 的上限,并且 Obj 被模式 M 中的某个任务使用
Modified := True
a := 最大上限 - 此模式的上限
将 Obj 在此模式下的上限提高 a
同时将满足以下两个条件的任务的优先级提高 a:
1. 在该模式下处于活动状态
2. 其优先级高于 Obj 的旧优先级
重新计算模式 M 中所有对象的上限
计算每个对象的最大上限优先级,应用公式(1)
结束 if
如果 Modified = True,则退出此 for 循环
结束 for 循环
如果 Modified = True,则退出此 for 循环
结束 for 循环
如果 Modified = False,则退出此循环
结束循环
需要注意的是,如果不同模式下不同对象的上限之间存在交叉关系,该算法将无法终止,这是一种特殊情况,我们将在下半部分进行讨论。
多模式实时系统中的上限协议:问题与解决方案(续)
特殊情况及另一种解决方案
特殊情况的描述
存在一种特殊情况,重新缩放算法无法解决。这种情况需要在执行重新缩放分析之前进行检测,并向用户发出警告或采用其他解决方案。具体描述为:如果一个对象在一种模式下的上限高于另一个对象的上限,而在其他任何模式下情况相反,那么重新缩放算法就无法应用。
假设我们有如图 3 所示的系统,每个任务 Ti 的优先级为 i,i 越大优先级越高。存在两个操作模式 M1 和 M2。在模式 M1 中,任务 T3 和 T1 使用对象 O2,任务 T2 使用对象 O1,O1 和 O2 的上限优先级分别为 2 和 3,即 O2 的上限高于 O1。在模式 M2 中,任务 T3 不活跃,O1 和 O2 的上限分别为 2 和 1,即 O2 的上限低于 O1。
如果盲目应用重新缩放算法,O1 的上限将为 2,O2 的上限将为 3。这在模式 M1 中是正确的,但在模式 M2 中,当 T2 准备执行而 T1 刚刚开始执行对 O2 的调用时,由于 IIPCP 的影响 T1 的优先级会提高到 3,从而导致过度阻塞。实际上,对于图 3 所示的系统,重新缩放算法永远不会终止。因为在模式 M2 中将 T1 的优先级提高到 3,就意味着要将 T2 在模式 M2 中的优先级至少提高到 4,从而使 O1 在模式 M2 中的上限变为 4,这又会影响其在模式 M1 中的上限,以此类推。虽然 T1 在模式 M2 中对 T2 引入的阻塞时间被限制在 O2 的最坏情况执行时间内,但在计算任务 T2 在模式 M2 中的响应时间时必须考虑这一点。
第二种解决方案:实现资源的不同版本
当应用上限的上限使系统不可行且重新缩放算法无法应用时,可以采用另一种方法,即针对每个模式实现对象的不同版本,每个版本具有不同的上限优先级。
以图 3 所示的情况为例,我们可以创建一个在模式 M1 中运行且上限优先级为 3 的受保护对象 O2M1,以及一个在模式 M2 中运行且上限优先级为 1 的受保护对象 O2M2。在 Ada 中,可以通过定义一个受保护类型,并为每个模式创建一个具有不同优先级的受保护对象作为该类型的实例来实现。例如,定义一个用于实现传感器的受保护类型:
protected type Sensor_Type (Ceiling: System.Priority) is
pragma Priority(Ceiling);
procedure Read(Value: out Sensor_Range);
procedure Set_Upper_Limit(New_Value: in Sensor_Range);
-- Other operations of the sensor
end Sensor_Type;
实例化一个上限优先级为 5 的具体传感器:
Sensor : Sensor_Type(Ceiling => 5);
为了保持不同版本对象状态的一致性,可以采用让所有版本访问同一个状态的方式,通过互斥操作来实现。例如,如果变量 Upper_Limit 是传感器状态的一部分,可以将其分配在一个包(如 Sensor_State)中,并实现一个受保护过程来设置该变量的值:
procedure Set_Upper_Limit(New_Value: in Sensor_Range) is
begin
Sensor_State.Upper_Limit := New_Value;
end Set_Upper_Limit;
这样,对象的数据只存在于一个地方(状态包),并受到 Ada 规则的保护。
复制受保护对象会带来一些成本,包括内存成本和计算成本。因为方法调用在选择合适的副本之前需要考虑当前的操作模式。例如,假设在“正常”模式下操作传感器的任务的最大优先级为 4,而在“紧急”模式下其最大优先级为 2。我们可以声明两个传感器:
Normal_Sensor : Sensor_Type(4);
Emergency_Sensor : Sensor_Type(2);
调用 Read 方法可以这样实现:
case Current_Operating_Mode is
when Normal => Normal_Sensor.Read(Value);
when Emergency => Emergency_Sensor.Read(Value);
-- More cases if needed
end case;
另一种方式是将受保护对象的不同版本存储在一个数组中,通过操作模式编号进行索引,这样可以增加一个间接层,但避免了使用 case 语句。例如:
-- Instantiation
Sensor : array(1..Modes_Nr) of Sensor_Type(Suitable_Ceiling);
-- Method call
Sensor(Current_Operating_Mode).Read(V);
其中,Suitable_Ceiling 可以是一个函数,用于返回每个版本对象的上限优先级。
结论
在固定优先级抢占式调度的实时系统中,IIPCP 是一种高效且安全的资源共享方法,而模式变化可以为系统带来重要的灵活性。但将两者结合时,可能会导致优先级的临时反转,在最坏情况下可能会导致任务错过截止日期。
重新缩放算法是一种在分析阶段静态解决该问题的方法,它根据任务与资源以及其他任务的关系为任务分配新的优先级,保留了任务的相对重要性顺序。然而,该算法的局限性在于系统提供的优先级级别数量以及不同模式下资源相对优先级反转的特殊情况。
实现资源的不同版本是一种更通用但成本更高的方法,它可以避免每个对象只有一个优先级的限制,适用于所有情况,包括重新缩放不可行的情况。通过复制对象可以消除不必要的阻塞问题,但会带来复制对象的内存成本和选择正确版本的时间成本。
无论是静态解决方案(重新缩放)还是对象复制方法,都可以与系统的静态可调度性分析集成,与速率单调或截止日期单调等成熟方法完全兼容。在实际应用中,应根据具体情况选择合适的解决方案,以确保系统的可调度性和性能。
解决方案 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
重新缩放算法 | 运行时无直接成本,仅在系统静态分析时起作用 | 受优先级级别数量和特殊情况限制 | 优先级级别充足且无特殊交叉关系时 |
实现资源不同版本 | 适用于所有情况,可消除不必要阻塞 | 有内存和计算成本 | 重新缩放不可行时 |
graph LR;
A[问题:优先级反转] --> B[重新缩放算法];
A --> C[实现资源不同版本];
B --> D[可调度系统];
C --> D;