自旋锁 死锁

以前在看linux操作系统时始终理解不了单CPU自旋锁导致死锁的问题.今天在网上搜了一下总算是理解了.摘录如下

想象你的内核代码请求到一个自旋锁并且在它的临界区里做它的事情,在中间某处,你的代码失去了处理器。或许它已调用了一个函数(copy_from_user,假设)使进程进入睡眠。也或许,内核抢占发威,一个更高优先级的进程将你的代码推到了一边(注意,这都是假设,自旋锁其实不允许这些操作)。此时,正好某个别的线程想获取同一个锁,如果这个线程运行在和你的内核代码不同的处理器上(幸运的情况),那么它可能要自旋等待一段时间(可能很长),当你的代码从休眠中唤醒或者重新得到处理器并释放锁,它就能得到锁。而最坏的情况是,那个想获取锁得线程刚好和你的代码运行在同一个处理器上,这时它将一直持有CPU进行自旋操作,而你的代码是永远不可能有任何机会来获得CPU释放这个锁了,这就是悲催的死锁。

自旋锁有几个重要的特性:1、被自旋锁保护的临界区代码执行时不能进入休眠。2、被自旋锁保护的临界区代码执行时是不能被被其他中断中断。3、被自旋锁保护的临界区代码执行时,内核不能被抢占。从这几个特性可以归纳出一个共性:被自旋锁保护的临界区代码执行时,它不能因为任何原因放弃处理器。


注:所以现代处理器在处理自旋锁时都会设定自旋上限时间以防死锁.
另自旋锁在单核非抢占式CPU上是无效的.被设为空操作,不做任何事.


可能你会奇怪,持有自旋锁的进程在执行内核代码时是不能被抢占的,那么为什么在可抢占式系统中有用呢.其实linux在设计可抢占式系统的自旋锁时只是把自旋锁设计为"只是禁止内核抢占",而没有自旋(所以使用自旋锁的代码一定要可以很快执行完,否则进程就一直持着锁不释放,也不可被抢占).可是理解为只是实现了一个不被打扰的原子操作,操作完后释放锁.所以它不能休眠.
linux上的自旋锁有三种实现:
1. 在单cpu,不可抢占内核中,自旋锁为空操作。
2. 在单cpu,可抢占内核中,自旋锁实现为“禁止内核抢占”,并不实现“自旋”。(注意)
3. 在多cpu,可抢占内核中,自旋锁实现为“禁止内核抢占” + “自旋”。

链接http://blog.csdn.net/vividonly/article/details/6594195

posted @ 2013-04-12 14:21  黑暗遊侠  阅读(1911)  评论(0编辑  收藏  举报