锁机制
原子操作
ATOMIC_INIT(int i) 定义原子变量的时候对其初始化。
原子位操作不像原子整形变量那样有个atomic_t 的数据结构,原子位操作时直接对内存进行的操作 void set_bit(int nr, void *p) 将 p 地址的第 nr 位置 1。
自旋锁 spinlock_t 表示自旋锁
1.用于多核SMP, 临界区不能太大
2.要注意死锁现象的发生 (线程与线程)
对于自旋锁而言,如果自选锁正在被线程A持有,线程B想要获取自旋锁,那么线程B就会处于忙循环-旋转-等待状态,线程B不会进入休眠或者说去做其他的处理,一直等待锁可以利用。
自旋锁 在运行期间会自动禁止抢占功能,当线程A在获得自旋锁的期间进入休眠状态,那么线程A会自动放弃CPU的使用权,线程B开始运行,线程B也想要获取锁,但是此时锁被A线程持有,而且内核还被禁止了抢占功能,线程b无法被调度出。此时就发生了死锁。
3.要注意死锁现象的发生 (线程与中断)
关闭本地中断 ,中断可以打断自旋锁。 (也就是降低中断优先级)
注意事项:
①、因为在等待自旋锁的时候处于“自旋”状态,因此锁的持有时间不能太长,一定要 短,否则的话会降低系统性能。如果临界区比较大,运行时间比较长的话要选择其他的并发处 理方式,比如稍后要讲的信号量和互斥体。
②、自旋锁保护的临界区内不能调用任何可能导致线程休眠的 API 函数,否则的话可能 导致死锁。
③、不能递归申请自旋锁,因为一旦通过递归的方式申请一个你正在持有的锁,那么你就 必须“自旋”,等待锁被释放,然而你正处于“自旋”状态,根本没法释放锁。结果就是自己 把自己锁死了!
④、在编写驱动程序的时候我们必须考虑到驱动的可移植性,因此不管你用的是单核的还 是多核的 SOC,都将其当做多核 SOC 来编写驱动程序。
DEFINE_SPINLOCK(spinlock_t lock) 定义并初始化一个自选变量。
spinlock_t lock; //定义自旋锁(声明一个自旋锁变量)
int spin_lock_init(spinlock_t *lock) 初始化自旋锁。
void spin_lock(spinlock_t *lock) 获取指定的自旋锁,也叫做加锁。
void spin_unlock(spinlock_t *lock) 释放指定的自旋锁。
int spin_trylock(spinlock_t *lock) 尝试获取指定的自旋锁,如果没有获取到就返回 0
int spin_is_locked(spinlock_t *lock) 检查指定的自旋锁是否被获取,如果没有被获取就 返回非 0,否则返回 0。
自旋锁API函数适用于SMP或支持抢占的单CPU下线程之间的并发访问, 也就是用于线程与线程之间,被自旋锁保护的临界区一定不能调用任何能够引起睡眠和阻塞的 API 函数,否则的话会可能会导致死锁现象的发生。
读写锁
顺序锁
信号量
信号量可以使等待资源线程进入休眠状态,因此适用于那些占资源比较久的场合。
信号量不能用于中断中,因为信号量会引起休眠,中断不能休眠
如果共享资源的持有时间比较短,那就不适合使用信号量了,因为频繁的休眠、切换线程引起的开销要远大于信号量带来的那点优势。
DEFINE_SEAMPHORE(name) 定义一个信号量,并且设置信号量的值为 1。 void sema_init(struct semaphore *sem, int val) 初始化信号量 sem,设置信号量值为 val。 void down(struct semaphore *sem) 获取信号量,因为会导致休眠,因此不能在中 断中使用。 int down_trylock(struct semaphore *sem); 尝试获取信号量,如果能获取到信号量就获 取,并且返回 0。如果不能就返回非 0,并且 不会进入休眠。 int down_interruptible(struct semaphore *sem) 获取信号量,和 down 类似,只是使用 down 进 入休眠状态的线程不能被信号打断。而使用此 函数进入休眠以后是可以被信号打断的。 void up(struct semaphore *sem) 释放信号量 表 47.4.2.1 信号量 API 函数
互斥量
mutex 可以导致休眠,因此不能在中断中使用mutex,中断中只能使用自旋锁。
和信号量一样,mutex保护的临界区可以调用引起阻塞的API函数,
因为一次只有一个线程可以持有mutex,因此 必须由mutex的持有者释放mutex。并且mutex不能递归上锁和解锁。
DEFINE_MUTEX(name) 定义并初始化一个 mutex 变量。 void mutex_init(mutex *lock) 初始化 mutex。 void mutex_lock(struct mutex *lock) 获取 mutex,也就是给 mutex 上锁。如果获 取不到就进休眠。 void mutex_unlock(struct mutex *lock) 释放 mutex,也就给 mutex 解锁。 int mutex_trylock(struct mutex *lock) 尝试获取 mutex,如果成功就返回 1,如果失 败就返回 0。 int mutex_is_locked(struct mutex *lock) 判断 mutex 是否被获取,如果是的话就返回 1,否则返回 0。 int mutex_lock_interruptible(struct mutex *lock) 使用此函数获取信号量失败进入休眠以后可 以被信号打断。

浙公网安备 33010602011771号