linux内核驱动自旋锁

本文详细介绍了自旋锁的概念及其在内核中的应用,包括传统自旋锁、读写自旋锁和顺序锁。自旋锁用于保护临界区,防止多个CPU同时访问,但可能导致CPU占用率高。读写自旋锁允许并发读取,而顺序锁则在读写之间提供更灵活的同步。文章列举了各种锁的使用场景和函数,并强调了避免死锁和阻塞的重要性。
摘要由CSDN通过智能技术生成

一、介绍
自旋锁,当加锁不成功时,自旋,自旋锁会不断的占用CPU进行变量的测试,由于属于原子操作,所以该CPU的占用会升为100%,所以,使用自旋锁时,临界区的代码需要很短,否则会影响系统性能,此外,作为锁机制的一种,使用自旋锁同样需要注意死锁的出现,自旋锁锁定期间不能调用可能引起进程调度的函数,如果进程获得自旋锁之后再阻塞,eg,copy_from_user(),copy_to_user(),kmalloc(),msleep()等,一旦阻塞发生就可能导致内核 崩溃

二、函数介绍
比较\类型 传统自旋锁 读写自旋锁 顺序锁 RCU机制
应用场合 需要上锁者独占的资源 需要写者独占的资源 很少同时读写的资源 读多写少的资源
读+读 并发 × √ √ √
读+写 并发 × × √ √
写+写 并发 × × × √
流程
抢锁-操作-解锁
示例


int cnt=0;
lock_t lock;
static int my_open()
{
    lock(&lock);
    if(cnt){
        unlock(&lock)
    }
    cnt++;
    unlock(&lock);
}
static int release()
{
    lock(&lock);
    cnt--;
    unlock(&lock);

传统自旋锁
锁定的临界区域不允许其他CPU访问,仍然会被中断和底半部的影响
将自旋锁+中断屏蔽来防止使用自旋锁访问临界资源的时候被中断打断


//定义并初始化自旋锁
spinlock_t spinlock
void spin_lock_init(spinlock_t *);
 
//加锁
//spin_lock - 加锁函数(忙等)
void spin_lock(spinlock_t *lock);
int spin_trylock(spinlock_t *lock);
spin_lock_irq();    //=spin_lock() + local_irq_disable()
spin_lock_irqsave(); //= spin_lock() + lock_irq_save();
spin_lock_bh();     //=spin_lock() + local_bh_disable();
 
//解锁
void spin_unlock(spinlock_t *lock);
spin_unlock_irq();    //=spin_unlock() + local_irq_enable()
spin_unlock_irqrestore(); //= spin_unlock() + lock_irq_restore();
spin_unlock_bh();     //=spin_unlock() + local_bh_enable();

static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
preempt_disable();
spin_acquire(&lock->dep_map, 0, 0, RET_IP);
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}
static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
{
local_irq_disable();
preempt_disable();
spin_acquire(&lock->dep_map, 0, 0, RET_IP);
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}
spin_lock_irq 禁止本地中断

读写自旋锁
允许多个CPU同时读临界资源,不允许同时写资源
读者 + 读者 不互斥
读者 + 写者 互斥
写者 + 写者 互斥


//include/linux/rwlock.h
//定义并初始化自旋锁
rwlock_t rwlock;
void rwlock_init(rwlock_t *lock);
 
//加读锁
void read_lock(rwlock_t *lock);
int read_trylock(rwlock_t *lock);
void read_lock_irqsave(rwlock_t *lock,unsigned long flags);
void read_lock_irq(rwlock_t *lock, unsigned long flags);
void read_lock_bh(rwlock_t *lock);
 
//解读锁
void read_unlock(rwlock_t *lock)
void read_unlock_irqrestrore(rwlock_t *lock,unsigned long flags);
void read_unlock_irq(rwlock_t *lock, unsigned long flags);
void read_unlock_bh(rwlock_t *lock);
 
//加写锁
void write_lock(rwlock_t *lock)
int write_trylock(rwlock_t *lock)
void write_lock_irqsave(rwlock_t *lock,unsigned long flags);
void write_lock_irq(rwlock_t *lock, unsigned long flags);
void write_lock_bh(rwlock_t *lock);
 
//解写锁
void write_unlock(rwlock_t *lock)
void write_unlock_irqrestrore(rwlock_t *lock,unsigned long flags);
void write_unlock_irq(rwlock_t *lock, unsigned long flags);
void write_unlock_bh(rwlock_t *lock);

顺序锁
读写锁的升级版,允许写者和读者同时访问临界区,临界区不能有指针
读者 + 读者 不互斥
读者 + 写者 不互斥 , 临界区没有指针+读者需自己注意更新
写者 + 写者 互斥

//include/linux/seqlock.h
//定义顺序锁
struct seqlock_t sl;
 
//获取顺序锁
void write_seqlock(seqlock_t *sl);
void write_tryseqlock(seqlock_t *sl);
void write_seqlock_irqsave(lock,flags); //=local_irq_save() + write_seqlock()
void write_seqlock_irq(seqlock_t *sl);  //=local_irq_disable() + write_seqlock()
void write_seqlock_bh(seqlock_t *sl);   //local_bh_disable() + write_seqlock()
 
//释放顺序锁
void write_sequnlock(seqlock_t *sl);
void write_sequnlock_irqsave(lock,flags); //=local_irq_restore() + write_sequnlock()
void write_sequnlock_irq(seqlock_t *sl);  //=local_irq_enable() + write_sequnlock()
void write_sequnlock_bh(seqlock_t *sl);   //local_bh_enable() + write_sequnlock()
 
//读开始
unsigned read_seqbegin(const seqlock_t *sl);
read_seqbegin_irqsave(lock,flags);  //=local_irq_save() + read_seqbegin();
 
//重读
int read_seqretry(const seqlock_t *sl,unsigned iv);
read_seqretry_irqrestore(lock,iv,flags);    //=local_irq_restore() + read_seqretry();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值