Linux的自旋锁spin源码解析

1. 概述——————————————————————

在Linux中提供了一些锁机制来避免竞争条件,最简单的一种就是自旋锁。引入锁的机制,是因为单独的原子操作不能满足复杂的内核设计需要。

例如,当一个临界区域要在,多个函数之间来回运行时,原子操作就显得无能为力了。

Linux中一般可以认为有两种锁,一种是自旋锁,另一种是信号量。这两种锁是为了解决内核中遇到的不同问题开发的。

自旋锁的作用:

 

自旋锁只有在内核可抢占或SMP(多处理器)的情况下才真正需要,在单CPU且不可抢占的内核下,自旋锁的所有操作都是空操作。

不是说在单CPU且不可抢占的内核下不可以用自旋锁,而是在同一时间内,没有其他程序跟你竞争临界资源,就算使用了自旋锁也无意义。

 

 

2.原理———————————————————————

结构体:

typedef struct spinlock {
	union {
		struct raw_spinlock rlock;
                //中间的DEBUG删除了
	       };
} spinlock_t;

初始化:

#define spin_lock_init(_lock)				\
do {							\
	spinlock_check(_lock);				\
	raw_spin_lock_init(&(_lock)->rlock);		\
} while (0)

上锁函数:

//          一般的上锁
static inline void spin_lock(spinlock_t *lock)
{
	raw_spin_lock(&lock->rlock);
}
//           通常用在进程中,用来禁止抢断和禁止软中断
static inline void spin_lock_bh(spinlock_t *lock)
{
	raw_spin_lock_bh(&lock->rlock);
}
//          判断有没有上锁
static inline int spin_trylock(spinlock_t *lock)
{
	return raw_spin_trylock(&lock->rlock);
}
//           既禁止本地中断,又禁止内核抢占
static inline void spin_lock_irq(spinlock_t *lock)
{
	raw_spin_lock_irq(&lock->rlock);
}

解锁函数:

static inline void spin_unlock(spinlock_t *lock)
{
	raw_spin_unlock(&lock->rlock);
}

static inline void spin_unlock_bh(spinlock_t *lock)
{
	raw_spin_unlock_bh(&lock->rlock);
}

static inline void spin_unlock_irq(spinlock_t *lock)
{
	raw_spin_unlock_irq(&lock->rlock);
}

static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
{
	raw_spin_unlock_irqrestore(&lock->rlock, flags);
}

上锁并保存之前的中断屏蔽状态

#define spin_lock_irqsave(lock, flags)				\
do {								\
	raw_spin_lock_irqsave(spinlock_check(lock), flags);	\
} while (0)
static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
{
	raw_spin_unlock_irqrestore(&lock->rlock, flags);
}

 

3.使用——————————————————————————

spinlock t lock;
unsigned int flags;
spin_lock_init (&lock);
spin_lock_irqsave(&lock, flags)	;  //上锁
/***********/

//临界资源

/*************/
spin_unlock_irqrestore(&lock, flags);  //解锁

注意:

自旋锁是一种忙等待

Linux中, 自旋锁当条件不满足时,会一直不断地循环条件是否被满足。如果满足,就解锁,继续运行下面的代码。这种忙等待机制是否对系统的性能有所影响呢?答案是肯定的。内核这样设计自旋锁确定对系统的性能,有所影响,所以在实际编程中,程序员应该注意自旋锁不应该长时间地持有,它 "是一种适合短时间锁定的轻量级的加锁机制。

自旋锁不能递归使用(即已经拿到锁的线程,不应该再等待拿到的那个锁)

这是因为, 自旋锁被设计成在不同线程或者函数之间同步。如果一个线程在已经持有自旋锁时,其处于忙等待状态,则已经没有机会释放自,己持有的锁了。如果这时再调用自身,则自旋锁永远没有执行的机会了。所以类似下面的递归形式是不能使用自旋锁的。

 

 

 

 

 

 

 

你可能感兴趣的:(Linux内核)