版权声明:转载请声明 https://blog.csdn.net/qq_40732350/article/details/83049367
1. 概述——————————————————————
在Linux中提供了一些锁机制来避免竞争条件,最简单的一种就是自旋锁。引入锁的机制,是因为单独的原子操作不能满足复杂的内核设计需要。
例如,当一个临界区域要在,多个函数之间来回运行时,原子操作就显得无能为力了。
Linux中一般可以认为有两种锁,一种是自旋锁,另一种是信号量。这两种锁是为了解决内核中遇到的不同问题开发的。
2.原理———————————————————————
结构体:
typedef struct spinlock {
union {
struct raw_spinlock rlock;
//中间的DEBUG删除了
};
} spinlock_t;
上锁函数:
// 一般的上锁
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);
}
3.使用——————————————————————————
spinlock t lock;
spin lock init (&lock);
spin lock (&lock);
//临界资源
spin unlock (&lock);
注意:
自旋锁是一种忙等待
Linux中, 自旋锁当条件不满足时,会一直不断地循环条件是否被满足。如果满足,就解锁,继续运行下面的代码。这种忙等待机制是否对系统的性能有所影响呢?答案是肯定的。内核这样设计自旋锁确定对系统的性能,有所影响,所以在实际编程中,程序员应该注意自旋锁不应该长时间地持有,它 "是一种适合短时间锁定的轻量级的加锁机制。
自旋锁不能递归使用(即已经拿到锁的线程,不应该再等待拿到的那个锁)
这是因为, 自旋锁被设计成在不同线程或者函数之间同步。如果一个线程在已经持有自旋锁时,其处于忙等待状态,则已经没有机会释放自,己持有的锁了。如果这时再调用自身,则自旋锁永远没有执行的机会了。所以类似下面的递归形式是不能使用自旋锁的。