章节列表

互斥信号量的原理与创建

2018-09-11 05:38:32 +0000 李述铜

从本小节开始,介绍互斥信号量的具体实现。

如果你看过操作系统相关的实现书籍。可以发现,资源的访问冲突问题是个值得关注的问题。互斥信号量正是解决这种问题的有效方案。

与计数信号量有所不同。互斥信号量可以看成是最大计数只能1的计数信号量,不过其实际功能还要复杂一些。为了满足一些特定的需求,增加了一些额外的控制字段及代码。

该模块的实现和计数信号量类似,也是基于事件控制块。在学习时,请同时参考《计数信号量的实现》章节。

主要内容

我们基于事件控制块设计了互斥信号量。相比计数信号量,其字段要多一些,但功能更为复杂。

重点难点

虽然课程中实现了互斥信号量,并且讲解了这种模块相比计数信号量的好处;但是这里还是要提一下下面的问题。

互斥信号量并不是必须

计数信号量也可以用于资源互斥访问,假如不考虑一些额外的需求。比如:

  • 不支持嵌套调用。通常是否嵌套调用是由你来决定的。你可以通过适当的安排避免嵌套调用;
  • 不支持所有者,任意任务都能发送通知。同样的,由谁来向信号量发送通知,也是由你写代码时决定的。你可以避免出现这样情况。
  • 无法解决优先级反转问题。这种情况可能不一定出现在你的应用中。 即便是出现,又有什么关系?大不了让高优先级的任务多等一会儿,你的应用中必须解决这种优先级反转的问题?

所以,对于一些简单的共享资源访问,可以直接用最大值为1的计数信号量替代。

优先级反转现像

该现像解释如下:

优先级翻转(Priority Inversion),是指某资源被较低优先级的进程/线程所拥有,较高优先级的进程/线程竞争该同步资源未获得该资源,而使得较高优先级进程/线程反而推迟被调度执行的现象。

课程中我们给出一幅示意图,解释了这种现像:

在这幅图中,低优先级任务一直被中优先级任务抢占无法运行,高优先级任务又期望占有低优先级任务的资源而等待。在这里再拿一个更为具体的实例解释。

在某些情况下,比如系统中突然出现了突然状况,你原本安排了某个高优先级任务处理。可能的处理方法是这样的:

  • 配置某个中断监测外部事件,一旦发生中断,通过事件标志组/信号量等通知高优先级任务
  • 高优先级任务初始化后,不断地事件标志组/信号量等待。一旦事件发生,立即转为运行态,处理该紧急事件。

假如这个高优先任务在处理紧急事件时,需要使用某个资源。但此时该资源被一个低优先级任务占有,所以在信号量上等待。

  • 如果此时没有优先级价于二者之间的其它任务,那么这个低优先级的任务将一直占用CPU运行,使用完资源释放,高优先级任务可以立即获得资源处理事件。
  • 但是如果此时有优先级介于二者之间的其它任务,这些任务可能数量不少,一直在占用CPU。那么低优先级任务一直无法运行,导致资源长期被该任务持有,无法释放,高优先级的任务也只好等待。直到低优先级任务获得足够多运行时间处理然后释放资源。

通过以上分析我们可以看到,优先级反转问题是否存在,取决于:

  • 当前持有资源的任务是否因优先级过低被其它较高优先级任务打断。如果其优先级仅比期望持有资源的任务优先级低1级,此时不算优先级翻转。因为此时运行的肯定是优先级更高的任务,这是合理的。
  • 高优先级任务尽快运行。一般来说,我们是将重要地需要紧急处理的事情放在高优级任务中,但实际设计中却不一定遵循该原则。

注意事项

应用实例

常见问题