前言:
在ucosiii中有可能会有多个任务访问共享资源,同时对这个共享资源操作时会出错,因此信号量最早是用来控制任务存取共享资源。现在信号量被用来实现任务之间的同步和Isr之间的同步。在可剥夺的内核中,当任务独占式使用共享资源时就会出现低优先级任务先于高优先任务运行的现象,这个现象称之为优先级翻转现象。为了解决这个问题,引出了互斥信号量的概念。
1:信号量
信号量是一种上锁机制,该任务必须获得相应的钥匙才能进入,直至代码执行结束,释放钥匙,程序才退出。信号量分两种,一种是二进制信号量,一种是计数型信号量。二进制信号量只有0和1两个值,计数型信号量可以有多个值。
(1)二进制信号量
当某个资源对应的信号量为1时,则表示这个资源可用;当为0时,则表示这个资源不可用。如果某个任务一直在等待,在超过等待时间后进入就绪状态。可以看出使用二进制信号量的资源,一次只能有一个任务使用这个资源。
(2)计数型信号量
多线程任务就会出现多个任务同时访问同一资源,这个时候二进制信号量就比较受限,不能多个任务同时访问,比较耗时间。如果使用的是计数型信号量就可以允许多个任务同时访问。每当有任务访问时 信号量数值加1,任务释放时减1.
2:优先级反转现象
优先级反转在可剥夺型内核中是非常常见的,在实时任务系统中不允许出现这样的情况出现,这样会破坏任务的预期顺序。先来看看到底什么是优先级反转现象:
(1)任务H和任务M处于挂起状态,等待某一事件的发生,任务L正在运行
(2)某一时刻任务L想要访问共享资源,在此之前必须获取对应资源的信号量
(3)任务L获取信号量后开始使用共享资源
(4)由于任务H的优先级高,他在某个事件发生后,剥夺了任务L的cpu使用权
(5)任务H开始运行
(6)任务H运行过程中也要 使用任务L正在使用的共享资源,由于信号量还在被任务L占用着,任务 H只能挂起等待信号量的到来
(7)任务L继续运行
(8)由于任务M的优先级也比 任务L的优先级高,所以,任务M剥夺了任务L的cpu使用权
(9)任务M执行
(10)任务M执行完后,释放cpu使用权,任务L继续执行
(11)任务L执行
(12)任务L执行完后,释放信号量,在切换到任务H
(13)任务H得到信号量后,继续执行
在以上给出例子中我们可以看到,实际上任务H的优先级是最高的,理论上他应该最先执行完,在等待任务L释放信号的时候,被任务M抢去了cpu的使用权,使得任务H等待的时间更加增长,这就相当于任务M的优先级高于任务H的优先级,导致优先级反转。
3:互斥信号量
为了避免优先级反转现象,ucosiii支持一种特殊的二进制信号量,叫互斥信号量。他究竟是怎么避免的呢?我们取个例子来看:
(1)任务H和任务M处于挂起状态,等待某一事件的发生,任务L正在运行
(2)某一时刻任务L想要访问共享资源,在此之前必须获取对应资源的信号量
(3)任务L获取信号量后开始使用共享资源
(4)由于任务H的优先级高,他在某个事件发生后,剥夺了任务L的cpu使用权
(5)任务H开始运行
(6)任务H运行过程中也要使用正在被任务L占有的共享资源,考虑到任务L正占用资源,ucosiii会把任务L的优先级提升到跟任务H一样的优先级,使得任务L能继续执行,不会被其他中等优先级任务打断。
(7)任务L以任务H的优先级运行,此时任务H并没有运行,因为共享资源的信号量在任务L手中,任务H还在等待它释放信号量
(8)任务L完成操作后,释放掉互斥信号量,ucosiii会将任务L的优先级恢复到提升之前的值,并释放了信号量
(9)任务H得到信号量后继续执行
(10)任务H访问完共享资源后,释放掉互斥信号量,
(11)此时没有优先级高于任务H的任务,所以继续执行任务H
(12)等任务H完成后,某一事件发生后,执行任务M
(13)任务M继续执行
互斥信号量只有任务才能使用,在中断服务程序中则不可以。ucosiii允许用户嵌套使用互斥信号量,一旦一个任务获得了一个互斥信号量,那么该任务可以对该互斥信号量嵌套使用250次,当然释放的时候也要释放相同的次数才能真正释放这个互斥信号量。