自旋锁-信号量-互斥体

linux内核中自旋锁使用注意事项:

(1).自旋锁实际上是忙等锁,当锁不可用时,CPU一直循环执行“测试并设备”该锁直到可用而取得该锁,CPU在等待自旋锁时不做任何有用的工作,仅仅是等待。因此只有在占用锁的时间极短的情况下,使用自旋锁才是合理的。当临界区很大,或有共享设备时候,需要较长时间占用锁的时候,使用自旋锁会降低系统的性能。
(2)自旋锁可能导致系统死锁。引发这个问题最常见的情况是递归使用一个自旋锁,即一个已经拥有了某个自旋锁的CPU想第二次获得这个自旋锁,则该CPU将死锁。

(3)自旋锁锁定期间不能调用可能引起进程调度的函数。如果进程获得自旋锁后再阻塞,如调用copy_from_user(),copy_to_user(),kmalloc(),和msleep等函数,则可能导致内核的崩溃。

(4)在单核情况下编程的时候, 也应该认为自己的CPU是多核的,驱动特别强调跨平台。例如,在单CPU情况下,若中断和进程可访问同一临界区,进程里调用spin_lock_irqsave()是安全的,在中断里其实不调用spin_lock()也是没有问题的。因为spin_lockl_irqsave()可以保证这个CPU的中断服务程序不可能执行。但是如果CPU变成多核,spin_lockl_irqsave()不能屏蔽另一外一个核的中断,多以另外一个核就可能造成并发问题。因此无论如何,我们在中断代码服务程序里也应该调用spin_lock()。

Linux中使用信号量注意事项:

(1).信号量不能使用在中断上下文中,因为获取信号量时,会导致休眠。

与自旋锁不同的是,当进程获取不到信号量时,进程不会原地打转而是进入休眠状态。 

Linux中使用互斥体注意事项:

(1).互斥体是进程级的,用于多个进程之间对资源的互斥,虽然也是在内核中,但是该内核执行路径是以进程的身份,代表进程来争夺资源的。如果竞争失败,会发生进程上下文切换,当前进程进入睡眠,CPU将运行其他进程,鉴于进程上下文切换开销也很大,因此只有当进程占用CPU资源时间较长时,用互斥体才是比较好的选择。

扫描二维码关注公众号,回复: 5989962 查看本文章

当所要保护的临界区访问时间比较短时,用自旋锁非常方便,因为他可以节省上下文切换的时间,但是CPU得不到自旋锁会在那里空转,直到其他执行单元,解锁为止,所以要求锁不能在临界区长时间停留,否则会降低系统的效率。

总结:1.当锁不能被获取到时,使用互斥体的开销是进程上下文切换时间,使用自旋锁的开销是等待获得自旋锁(由临界区执行时间决定)。若临界区较小,宜使用自旋锁,若临界区较大,应该使用互斥体。

     2.互斥体所保护的临界区可能包含可能引起阻塞的代码,而自旋锁则绝对要避免用来保护包含这样代码的临界区,因为阻塞意味着要进行进程的切换,如果进程被切换出去后,另一个进程企图获取本自旋锁,死锁就会发生。

3.互斥体存在于进程上下文,因此如果被保护的共享资源需要在中断或软中断情况下使用,则在互斥体和自旋锁之间只能选择自旋锁,如果一定要使用互斥体,则只能通过mutex_trylock()方式进行,不能获取就立即返回以避免阻塞。

猜你喜欢

转载自blog.csdn.net/u012830148/article/details/88395890
今日推荐