单核:
系统杀伤力: 睡眠锁<关调度<关中断
安全程度: 睡眠锁<关调度<关中断
推荐指数: 睡眠锁>关调度>关中断
SMP核:
相对于单核,SMP核多了一个自旋锁进行多核同步的机制。
系统杀伤力: 睡眠锁<关调度<关中断<自旋锁
安全程度: 睡眠锁<关调度<关中断<自旋锁
推荐指数: 睡眠锁>关调度>关中断>自旋锁
关闭调度有两种语义,一种是全局调度器的关闭,另一种是任务调度器的关闭,任务级调度器的关闭后,仅仅关闭了抢占调度,但仍然是可以主动调度的。也有一部分系统,关闭中断的上下文可以安全调度,上面讨论不包括这两种case.
关中断和关调度实际上是两个正交的概念,这一点从 spin_lock/spin_unlock,spin_lock_irq/spin_unlock_irq, spin_lock_irqsave/spin_unlock_irqrestore的定义都可以看的出来。
spin_lock/spin_unlock | 只获取锁,不进行中断操作 |
spin_lock_irq/spin_unlock_irq | 获取锁,关闭/打开中断,如果执行spin_lock_irq之前中断是关闭的,执行后将会打开中断。 |
spin_lock_irqsave/spin_unlock_irqrestore | 获取锁,关闭/恢复中断,如果执行spin_lock_irqsave前中断是关闭的,执行spin_unlock_irqrestore后中断仍然关闭。 |
在mutex的实现中,如果mutex当前被占用,则后面尝试获取的client1, client2, client3.....将会简单在mutex中进行登记之后进入休眠状态,等到mutex的拥有者释放后唤醒任意一个CLIENT(依赖于唤醒算法)。而spin_lock则不同,顺序锁实现的spin_lock将严格按照client的进入顺序转交自旋锁。
总结:
1.临界区的目的是将都资源的乱序访问顺序化,保证在任何系统处于正常运行级的时候,资源描述都是完整的。
2.在多核情况下,出现了一种新的资源共享情况,即是核间共享资源,单纯禁止中断显然不能满足临界区要求,因为处理器核心与核心之间互相独立,一个处理器核心不能禁止在另一个处理器核心上的中断,必须使用自旋锁及案例临界区。
3.包括互斥锁,信号量,事件等机制在内的睡眠锁,可以针对资源独立设锁,这样保障不共享资源的任务没必要被串行化,允许不共享同一个资源任务之间的并发,具备一定的并发度,对系统影响最小。
举一个生活中的例子,一个路口的交通阻塞没必要关闭整个城市的交通。
4.spin_lock本身也可以针对资源独立设锁,但是其实现已经包含了关中断和关调度的语义,是临界区中最狠的。
5.锁问题的本质是资源问题,遇到问题的试着先不要考虑锁,先考虑资源试试?
6.需要硬件提供最原始的原子语义,系统方能在此基础之上构建原子操作大厦,通常对单核系统,最本源的原子语义是关中断,这在现代处理器上很容易得到满足,其次是关调度和基于这两种原子语义构建更加复杂的semophore,mutex等等。对于多核系统,仅提供关中断语义还不够,还需要系统提供spin_lock的实现语义,例如链接-存储指令,总线锁等等,自旋锁单纯依赖软件是无法实现的。必须由硬件架构层面进行支持。