前面两篇文章,介绍的锁机制都是可用于可睡眠的线程中,但是自旋锁可以用于中断上下文中,因为他是不可睡眠的锁。
自旋锁用于中断上下文,不能用于进程上下文,它是不可睡眠的锁,该进程若有睡眠,就不能使用该锁,因为会发生死锁。
在内核中,自旋锁机制是如果当前可获得自旋锁则代码进入临界区,如果当前锁不可获得,则代码进入忙循环中并时刻检查该锁,知道锁可用。所以这个忙循环就是自旋锁的“自旋”部分。
1、头文件:include/linux/spinlock.h
结构体:spinlock_t lock;
2、定义及其初始化自旋锁:
277 #define spin_lock_init(_lock) \ 278 do { \ 279 spinlock_check(_lock); \ 280 raw_spin_lock_init(&(_lock)->rlock); \ 281 } while (0)
3、自旋锁的使用:
锁机制的使用都是一样的,再进入临界区之前获得锁。
获得自旋锁:
283 static inline void spin_lock(spinlock_t *lock) 284 { 285 raw_spin_lock(&lock->rlock); 286 }
注意:所有的自旋锁在本质上都是不可中断的,一旦调用了自旋锁,在获得锁之前一直处于等待状态。
释放自旋锁:
323 static inline void spin_unlock(spinlock_t *lock) 324 { 325 raw_spin_unlock(&lock->rlock); 326 }
4、在使用自旋锁时,需要注意的问题:
如果某工作获得自旋锁,那么他就不能睡眠,因为一旦睡眠了,将没有一个任务可以唤醒它,其他线程想要获得该自旋锁,好的情况是等待很长的时间,最坏的情况是系统进入死锁状态,所以使用自旋锁的原则之一就是:任何拥有该自旋锁的代码都必须是原子的,并且不能睡眠;
拥有自旋锁的原则二:自旋锁必须在很短的时间内获得,长的锁拥有的时间将会阻止队当前处理器的调度,这就意味着更高优先级的进程不得不等待;
自旋锁用于可休眠的线程中,比如在用户空间和用户空间之间复制数据就可以休眠,需要分配内存的任何操作也会休眠,比如:kmalloc。
浙公网安备 33010602011771号