最后编辑于: 2008-08-27 16:48 | 分类: linux | 标签: 自旋锁 | 浏览数: 1309 | 评论数: 0
A: 信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进程上下文使用(_trylock的变种能够在中断上下文使用)
Q: 这个确实如此, 如果在中断上下文中,使用信号量(也就是在中断处理函数中使用信号量) ,可能会导致死锁 , 而spinlock ,由于是自旋,不会睡眠,而且,spinlock保护的代码都非常短 , 所以都能很快获得spinlock ,不会造成死锁。
A: 而自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用。
Q: 确实如此!
A: 如果被保护的共享资源只在进程上下文访问,使用信号量保护该共享资源非常合适,如果对共享资源的访问时间非常短,自旋锁也可以。
Q: 参考了一些driver的代码,确实应该遵循这个原则, 比如:
spin_lock_irq(&rtc_lock);//禁止本地中断, 因为返回给用户的就是这个rtc_irq_data ,如果恰好发生了中断,这个value就被窜改了
data = rtc_irq_data; /* 由中断函数更新*/
//显然这里有竟态条件,这里要访问,但是中断处理函数也要修改(write) ,所以就要禁止中断
rtc_irq_data = 0;
spin_unlock_irq(&rtc_lock);
显然这里用自旋锁,就比用信号量强。 因为中断函数,更新rtc_irq_data的速度很快, 这里马上就可以获得lock,最主要的原因还是 在中断处理函数中不能使用信号量,防止死锁。
A: 自旋锁保持期间是抢占失效的,
Q: 自旋锁抢占失效的意思, 我的理解是,比如2.6 kernel ,如果某个kernel线程(可能就是某个用户进程的延伸) ,如果获得了某个自旋锁,即使有更高优先级的进程需要调度, 当前的获得了自旋锁的线程,也不会放弃这个锁,或者说,也不会失去CPU 。
A: 而信号量和读写信号量保持期间是可以被抢占的。
Q: 如果是这样,如果高优先级的进程也恰好也要获取信号量呢,而刚才那个进程并没有释放信号量啊?
便于说明 :A表示低优先级的, B表示高优先级。 当a 获得信号量以后, 进入临界区 , 就在还没有退出临界区时候, 被B抢占 , B恰好也要获取信号量, 如果A没有释放信号量,B 就必然一直等着,进入sleep状态 , 直到又一次发生了进程切换, 等到A 再一次被调度的时候, A 从临界区出来 ,释放信号量 , 又一次调度 ; 等到最后又调度B的时候 , B 终于可以获得信号量了。
不知道我这个情景分析的对不对呢? 如果对的话, 这样看来, 在刚才的情景之下, 用自旋锁反而更好一些, 防止了抢占,也能使A进程更快的从临界区出来。
spin_lock(lock)
该宏用于获得自旋锁lock,如果能够立即获得锁,它就马上返回,否则,它将自旋在那里,直到该自旋锁的保持者释放,这时,它获得锁并返回。总之,只有它获得锁才返回。
spin_lock_irqsave(lock, flags)
该宏获得自旋锁的同时把标志寄存器的值保存到变量flags中并失效本地中断。
spin_lock_irq(lock)
该宏类似于spin_lock_irqsave,只是该宏不保存标志寄存器的值。
实际上,这一段应该能很好的说明这个问题了, “spin_lock 与 spin_lock_irq 的区别”。