互斥量的优先级继承机制
在RT-Thread操作系统中为了降低优先级翻转问题
利用了优先级继承算法
。优先级继承算法是指,暂时提高某个占有某种资源的低优先级线程的优先级,使之与在所有等待该资源的线程中优先级最高那个线程的优先级相等
,而当这个低优先级线程执行完毕释放该资源时,优先级重新回到初始设定值。因此,继承优先级的线程避免了系统资源被任何中间优先级的线程抢占。
互斥量和二值信号量的区别
互斥量与二值信号量最大的不同是:互斥量具有优先级继承机制
,而信号量没有。也就是说,某个临界资源受到一个互斥量保护,如果这个资源正在被一个低优先级线程使用,那么此时的互斥量是闭锁状态,也代表了没有线程能申请到这个互斥量,如果此时一个高优先级线程想要对这个资源进行访问,去申请这个互斥量,那么高优先级线程会因为申请不到互斥量而进入阻塞态,那么系统会将现在持有该互斥量的线程的优先级临时提升到与高优先级线程的优先级相同,这个优先级提升的过程叫做优先级继承。这个优先级继承机制确保高优先级线程进入阻塞状态的时间尽可能短,以及将已经出现的“优先级翻转”危害降低到最小
。
线程的优先级在创建的时候就已经是设置好的,高优先级的线程可以打断低优先级的线程,抢占CPU的使用权。但是在很多场合中,某些资源只有一个,当低优先级线程正在占用该资源的时候,即便高优先级线程也只能乖乖的等待低优先级线程使用完该资源后释放资源。这里高优先级线程无法运行而低优先级线程可以运行的现象称为“优先级翻转”。
现在有3个线程分别为H线程(High)、M线程(Middle)、L线程(Low),3个线程的优先级顺序为H线程>M线程>L线程。正常运行的时候H线程可以打断M线程与L线程,M线程可以打断L线程。
(1)
:L线程正在使用某临界资源, H线程被唤醒,执行H线程。但L线程并未执行完毕,此时临界资源还未释放。(2)
:这个时刻H线程也要对该临界资源进行访问,但 L线程还未释放资源,由于保护机制,H线程进入阻塞态,L线程得以继续运行,此时已经发生了优先级翻转现象。(3)
:某个时刻M线程被唤醒,由于M线程的优先级高于L线程, M线程抢占了CPU的使用权,M线程开始运行,此时L线程尚未执行完,临界资源还没被释放。(4)
:M线程运行结束,归还CPU使用权,L线程继续运行。(5)
:L线程运行结束,释放临界资源,H线程得以对资源进行访问,H线程开始运行。
在这过程中,H线程的等待时间过长,这对系统来说这是很致命的,所以这种情况不允许出现,而互斥量就是用来降低优先级翻转的产生的危害。
假如有优先级继承呢?那么,在H线程申请该资源的时候,由于申请不到资源会进入阻塞态,那么系统就会把当前正在使用资源的L线程的优先级临时提高到与H线程优先级相同
,此时M线程被唤醒了,因为它的优先级比H线程低,所以无法打断L线程,因为此时L线程的优先级被临时提升到H,所以当L线程使用完该资源了,进行释放,那么此时H线程优先级最高,将接着抢占CPU的使用权, H线程的阻塞时间仅仅是L线程的执行时间,此时的优先级的危害降到了最低。
(1)
:L线程正在使用某临界资源, H线程被唤醒,执行H线程。但L线程并未执行完毕,此时临界资源还未释放。(2)
:某一时刻H线程也要对该资源进行访问,由于保护机制,H线程进入阻塞态。此时发生优先级继承,系统将L线程的优先级暂时提升到与H线程优先级相同,L线程继续执行。(3)
:在某一时刻M线程被唤醒,由于此时M线程的优先级暂时低于L线程,所以M线程仅在就绪态,而无法获得CPU使用权。(4)
:L线程运行完毕,H线程获得对资源的访问权,H线程从阻塞态变成运行态,此时L线程的优先级会变回原来的优先级。(5)
:当H线程运行完毕,M线程得到CPU使用权,开始执行。(6)
:系统正常运行,按照设定好的优先级运行。
但是使用互斥量的时候一定需要注意:在获得互斥量后,请尽快释放互斥量,同时需要注意的是在线程持有互斥量的这段时间,不得更改线程的优先级。
另外需要注意的是互斥量不能在中断服务函数中使用
。
互斥量的运作机制
用互斥量处理不同线程对临界资源的同步访问时,线程想要获得互斥量才能进行资源访问,如果一旦有线程成功获得了互斥量
,则互斥量立即变为闭锁状态
,此时其他线程会因为获取不到互斥量而不能访问这个资源
,线程会根据用户自定义的等待时间进行等待
,直到互斥量被持有的线程释放
后,其他线程才能获取互斥量从而得以访问该临界资源
,此时互斥量再次上锁,如此一来就可以确保每个时刻只有一个线程正在访问这个临界资源
,保证了临界资源操作的安全性。
互斥量控制块
本节笔记参考于:野火-《RT-Thread内核实现与应用开发实战》
韦东山 《RT-Thread完全开发手册之内核机制》
以及RT-Thread官网:互斥量