英文: Priority Inversion
中文: 优先级翻转、优先级倒置、优先级逆转
介绍: 即当一个高优先级任务通过信号量机制访问共享资源时,该信号量已被一低优先级任务占有,而这个低优先级任务在访问共享资源时可能又被其它一些中等优先级任务抢先,因此造成高优先级任务被许多具有较低优先级任务阻塞,实时性难以得到保证。
简单从字面上来说,就是低优先级的任务先于高优先级的任务执行了,优先级搞反了。
例:假设三个任务准备执行,A、B、C,优先级依次是A > B > C:
首先: C处于运行状态,获得CPU正在执行,同时占有了某种同一时间只能一个任务访问的资源S。
其次: A进入就绪状态,因为其优先级比C高,所以获得CPU,此时A转为运行状态;C因为CPU被夺取而进入就绪状态;
第三: A执行过程中发现需要使用上述的那个资源S,但发现这个资源又被等待中的C占有的,于是A进入阻塞状态(因为该资源以及被C占有了,所A只能等),C又回到运行状态;
第四: 此时B进入就绪状态,准备开始执行了,因为其优先级也比C高,所以B获得CPU,进入运行状态;C又因为CPU被夺取回到就绪状态;
第五: 如果这时又出现了B2、B3、B4等各种任务,他们的优先级都比C高,但都比A低,那么就会出现高优先级任务的A不能执行,反而低优先级的B、B2、B3、B4等低优先级的任务可以执行的奇怪现象,而这就是优先级反转。
如上例,由于稀缺资源S的独占性,也即同一时间只能有一个任务进行访问,高优先级的任务A必须等到低优先级的任务C完成了对该稀缺资源的使用并释放该资源后(相应的释放信号量)才能继续执行,也即如果低优先级的任务C一直不释放该资源,高优先级任务A就只能一直等一直等,也就意味着高优先级任务A的执行变相的取决于了低优先级任务C释放该资源的这个动作。
但期间如果还存在比任务C高优先级的任务需要执行,这些任务发现只有比它优先级低的任务C需要使用CPU,比它优先级高的任务A虽然也存在,但任务A已经因为获取不到资源而阻塞在那,这样便会先于任务C执行,并且此时高优先级的任务A因为阻塞而并没有执行。
这样在从任务A创建开始,到任务C执行释放相应临界资源的这个动作的这段时间内,只要存在相应优先级高于任务C的任务便都能执行,而高优先级的任务A反而没有得到执行。
可见我们虽然给任务A划分了很高的优先级希望该任务能够优先执行,但因为其需要访问一稀缺资源,但该稀缺资源已经被一低优先级的任务所占用,便会产生上述这种现象,也即产生优先级反转,关键原因还是在于稀缺资源的独占性。
首先优先级反转这个概念,往往都是在嵌入式领域内,尤其是嵌入式实时系统方面,嵌入式实时操作系统,最最重要的指标就是:确保任务执行时间是可预测的,即涉及到最后期限deadline。 需要确保任何时刻,执行某个任务,都不能超过某个时间。
例:对于上述的任务A,需求该任务必须在1ms内完成,但因为期间因为需要等待任务C释放临界资源,让B、B2、B3、B4等各种低优先级任务先执行了,这样就必然会导致无法在指定的1ms内完成。
这样就由于优先级反转,造成任务调度时时间的不确定性,时间的不确定性也就破坏了实时系统的实时性,严重时可能导致系统崩溃,由于本身基于优先级设计的任务,每个优先级不同的任务,往往对应着实际的现实中的执行的任务顺序,但其相应的优先级反转,导致低优先级比高优先级先执行了,也就直接导致了任务错乱,逻辑错乱了。
例:当年火星探路者号(Mars Pathfinder),使用的VxWorks系统,就由于优先级反转而导致了内部执行逻辑出错的bug。
如上,由于稀缺资源S的独占性,要想高优先级的任务A优于的低优先级的任务B、B2、B3、B4等先执行,有如下两种方法:
方法一显然不行,因为独占资源没有操作完成就释放,要么回滚,要么出错,而方法二修改相应的任务优先级显然是可行的,所以相应的有如下三种解决方法:
当任务C使用资源S时,就把任务C的优先级提升到能临界访问资源S的最高优先级,执行完成释放资源之后,再把优先级改回来。
也即将申请该资源任务的优先级提升到可能访问该资源的所有任务中最高优先级任务的优先级(这个优先级称为该资源的优先级天花板),相应的只要有任务访问该临界资源,都会拥有一个相同的优先级
这样的方法,简单易行,解决了多个高优先级任务抢占资源S的问题,但也带来了一些缺点,就是不一定每次都有高优先级任务抢占资源S,所以每次都提升优先级都是对CPU资源的一种浪费。
当任务C使用资源S时,任务A抢占执行权,申请资源C,比较任务A和任务C的优先级,假如任务A优先级高,便将任务C的优先级提升到和任务A相同的优先级,当任务C释放资源后,再将优先级再调整回来。
也即当发现高优先级的任务因为低优先级任务占用资源而阻塞时,就将低优先级任务的优先级提升到等待它所占有的资源的最高优先级任务的优先级。
相对于优先级天花板方法,相当于延后执,每次CPU操作必然是存在优先级反转的现象,自己本身的特点是,逻辑复杂,需要操作系统支持相同优先级。在ucos中不容易实现。
两者结合的方案:当任务C使用资源S时,任务A抢占执行权,申请资源S,比较资源A和资源C的优先级,假如任务A优先级高,便将任务C提升到能访问资源S的最高优先级(该资源的优先级天花板),当任务C释放资源后,将优先级再调整回来。
这种方式相比于优先级继承则逻辑更加简单。
注:上述情况的任务肯定都是基于优先级调度的,也即在一次CPU调度内优先级高的任务先执行。