互斥信号量
操作系统中利用信号量解决进程间的同步和互斥(互斥信号量)的问题,在多道程序环境下,操作系统就是遮掩实现进程之间的同步和互斥。但是在使用的过程中厉害的前辈还是发现了这一优秀机制的缺陷,它会导致优先级翻转从而出现系统部分功能瘫痪严重则会导致系统崩溃,互斥信号量的出现是为了解决优先级反转的问题的。根据互斥信号量的数据结构可以看出来互斥信号量和多值信号量在相关函数的操作是很相似的。
其中互斥信号量三个特有的不同变量的含义分别是:
1.OwnerTCBPtr
2.OwnerOriginalPrio
3.OwnerNestingCtr
优先级反转:
优先级反转在可剥夺内核中是非常常见的,在实时系统中不允许出现这种现象,这样会破坏任务的预期顺序,可能会导致严重的后果。如下图(图片来源:原子USOC教程)
图中的三个任务的优先级分别是高(H) 中(M) 低(L),其中中等优先级任务不需要请求信号量,其他两个任务执行会请求同一块资源也就是同一个信号量。系统在运行时会有这种情形,最低优先级的任务L先请求信号量并且成功请求到开始运行了,此时高优先级任务H和M就绪并H优先级最高拿走了CPU使用权,但是H任务内请求信号量的地方因为任务L还没有执行完所以还没有释放信号量导致H任务被挂起,此时CPU使用权就“风水轮流转”的到M任务,M任务开始执行直到执行完成,然后L任务才的以继续执行直到完成并释放掉信号量,最后H任务才能继续执行。这个过程中任务设计时如果计划让H任务完成了一些处理工作后才能执行任务M但是,似乎并没有按设计的流程执行导致中优先级的任务先于高优先级的人任务执行了,这就称之为优先级反转,这种现象在实际使用很可能导致严重的问题。
对于互斥信号量同样的三个优先级的任务,但在高任务请求信号量时因为互斥信号量此时被低优先级的任务拥有,所以会将L任务优先级暂时提高的H的水平,此时就可以理解互斥信号量内保存原优先级的变量的作用了就是在释放信号量时还原原优先级的备份,此时执行的过程就是最低优先级的任务L的以继续运行,此时高优先级任务H和M都就绪,但是L任务此时的优先级高于M所以CPU使用权还在L,当L执行完成后释放掉信号量优先级也降回原来的级数,此时H任务和M任务同样处于就绪状态并H拿走了CPU使用权,此时CPU使用权就不会给中优先级M然后M任务最后执行。这样执行顺序就没有问题了。
在前面多值信号量上的基础上互斥信号量的相关操作相对就简单好理解了不少;
1,创建互斥信号量
定义一个互斥信号量,然后调用创建互斥信号量,同样每个信号量都有一个等待队列,且由OS_PEND_LIST变量管理,TailPtr指向等待队列的最后一个,Head指向第一个如图的数据结构;互斥信号量加入了信号量的拥有者来标记信号的当前拥有着任务。这点和多值信号量相同。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2,请求信号量此时如果已经有低优先级的任务占有信号量要进行优先级的提升操作,提升了优先级也需要修改等待队列因为这个队列是按照优先级高低排序的,同时要是任务处于就绪状态也需要修改就绪列表里的顺序原因同上。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
3,发布信号量
这里由于互斥信号量的属性决定的,互斥信号量的发布函数调用任务须先拥有互斥信号量。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
其中的详细操作函数在多值信号量就已经见过了就是同多值信号量一样。
4,接下来就是一些强制解除等待,删除信号量函数等相关的函数了。这些函数其实就是对等待队列的一些修改函数和互斥信号量的整体原理关系不是十分紧密。
强制解除等待
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
注意解除等待和删除函数的区别就是没有优先级继承恢复的相关操作,这个暂时还没有理解为什么。
删除信号量
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
这里主要区别一下多值信号量的相关操作的不同就可以,其基本的操作及原理都和多值信号量类似多了的部分就是其特点,也是其操作和多值信号量的不同点。