- 论坛徽章:
- 0
|
Linux小品2:自旋锁
自旋锁和互斥锁有点类似,但是想象一种情况:线程要获取互斥锁,没有得到此锁,就进入睡眠状态,但是此锁的保持时间一般都非常的短,进入睡眠的线程立刻被唤醒。那么进入睡眠,再到被唤醒这个过程的代价就有点大了,此时最好的方法是不要让线程进入睡眠,而是不停的去查看锁是否释放,那么这种情况下就需要使用自旋锁,而不是互斥锁。
当情况不同,我们选择不同的锁。如果锁的保持时间一般很短,最好是使用自旋锁,这样就有很高的效率,因为省去了睡眠和唤醒的代价。如果锁的保持时间长,最好使用互斥锁,因为如果线程不停的去“自旋”查看锁是否释放,那CPU就白白浪费了。
【include/linux/spinlock_types.h】
自旋锁的普遍的定义和初始化函数。
typedef struct {
raw_spinlock_t raw_lock;
#ifdef CONFIG_GENERIC_LOCKBREAK
unsigned int break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
unsigned int magic, owner_cpu;
void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
} spinlock_t;
spinlock_t的结构体定义
如何初始化一个自旋锁?
Linux定义了一个宏,用于初始化一个自旋锁。代码如下:
----------------------------------------------------------------------------------------------------------------
# define __SPIN_LOCK_UNLOCKED(lockname) \
(spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED, \
.magic = SPINLOCK_MAGIC, \
.owner = SPINLOCK_OWNER_INIT, \
.owner_cpu = -1, \
SPIN_DEP_MAP_INIT(lockname) }
--------------------------------------------------------------------------------------------------------------------
并且又定义了一个宏,DEFINE_SPINLOCK()其中的区别请参照源代码中的一段注释:
----------------------------------------------------------------------------------------------------------------------------
/*
* SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED defeat lockdep state tracking and
* are hence deprecated.
* Please use DEFINE_SPINLOCK()/DEFINE_RWLOCK() or
* __SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED() as appropriate.
*/
----------------------------------------------------------------------------------------------------------------------------
#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
自旋锁是内核中常用的锁。
加锁是对数据而不是代码,所有的自旋锁在本质上是不可中断的。
自旋锁可以使用在中断处理程序中,而信号量则不能,因为信号量可能导致睡眠。在中断处理程序中使用自旋锁时,一定要在获取锁之前,首先禁止本地中断(在当前处理器上的中断请求),否则中断处理程序就会打断正持有锁的内核代码,有可能试图去争用这个已经被持有的自旋锁。
适用于自旋锁的核心规则是:任何拥有自旋锁的代码都必须是原子的。它不能被休眠,事实上,它不能因为任何原因放弃处理器,除了服务中断以外。内核抢占的情况由自旋锁代码本身处理,任何时候,只要内核代码拥有自旋锁,在相关处理器上的抢占就会被禁止。
函数spin_lock_bh用于获取指定锁,同时它会禁止所有下半部的执行。由于下半部会抢占进程上下文中的代码,所以当下半部与进程上下文共享数据时,必须对进程上下文中的共享数据进行保护。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/110359/showart_2149551.html |
|