一、概述
在kernel中,发生并发访问的发生源主要为一下4种方式
1、中断和异常,中断发生之后,中断处理函数与被中断进程之间有可能会出现资源并发访问
2、软中端以及tasklet,软中断以及任务调度都会打断当前的进程,从而发生资源的并发性访问
3、内核抢占,内核抢占也是会打断当前的进程,从而造成资源的并发性访问
4、smp,多个CPU也会对同一个资源进行并发性的访问。
为了解决资源并发性的访问从而造成意料之外的现象,linux内核提供了几种保护机制。
比如spinlock,atomic,semphorema,mutex和 write read lock以及rcu。
今天我们主要聊一聊spin_lock这个在驱动中使用较为常见的资源保护机制
二、spin_lock介绍
2.1 引入
对引用计数这些如果使用lock机制,就会造成额外的系统开销,但是在驱动中,我们大多数都是资源的拷贝,解析这些需要大量CPU资源的操作,同时也需要保护这部分数据的操作的有效性,spin_lock是一个非常不错的选择。
spin_lock是一个忙等待的工作方式,如果两个进程同时访问资源,但是其中一个进程以及获取到该资源后,就会对资源加上一把自旋锁,另外一个资源只有在死循环等待前一个进程释放该锁之后才可以对资源进行访问,所以:spin_lock是忙等待的工作方式。
2.2、一些小谈
**假设:**在spin_lock的临界区出现了睡眠,tasklet等会出现什么样的后果勒?
答:1、tasklet或者睡眠之后,下一个进程可能会访问临界区中的资源,从而进行加spin_lock,这就造成了我们常见的死锁问题了。
2、spin_lock设计是一个忙等待机制,如果临界出现了进程的切换或者调度,都与spin_lock的设计机制相悖。
**假设2:**如果在spin_lock的临界区发生了外部硬件中断该如何处理
答:这时候我们需要引入spin_lock的变种了,spin_lock_irq()了,spin_lock_irq()会在获取spin_lock之前会关闭本地中断,从而避免了死锁问题。
总结:
合理的使用spin_lock是每一个驱动工程师应该学会的机能,在普通函数中防止资源的并发性使用spin_lock,但是在中断中防止资源的并发性使用spin_lock_irq(),它会在spin_lock之前将本地的中断关闭,从而避免了spin_lock的死锁发生。