同步与互斥

同步与互斥


因为工作原因,想系统的学习下驱动,参考韦东山嵌入式视频,做一些笔记

1 需要同步互斥的原因

2 内核中实现同步互斥的常用方法

2.1 原子操作

2.1.1 实现方式

在原子操作中,架构以ARMv6位分界点,实现方式有所不同

架构实现
<ARMv6(不支持SMP)1 关中断 2 操作变量 3 恢复中断
>=ARMv6使用strex和sdrex多次尝试
函数名作用
atomic_read(v)读出原子变量的值,即v->counter
atomic_set(v,i)设置原子变量的值,即v->counter = i
atomic_inc(v)v->counter++
atomic_dec(v)v->counter–
atomic_add(i,v)v->counter += i
atomic_sub(i,v)v->counter -= i
atomic_inc_and_test(v)先加1,再判断新值是否等于0;等于0的话,返回值为1
atomic_dec_and_test(v)先减1,再判断新值是否等于0;等于0的话,返回值为1

2.2 原子位操作

下表中p是一个unsigned long指针

函数名作用
set_bit(nr,p)设置(*p)的bit nr为1
clear_bit(nr,p)清除(*p)的bit nr为0
change_bit(nr,p)改变(*p)的bit nr,从1变为0,或是从0变为1
test_and_set_bit(nr,p)设置(*p)的bit nr为1,返回该位的老值
test_and_clear_bit(nr,p)清除(*p)的bit nr为0,返回该位的老值
test_and_change_bit(nr,p)改变(*p)的bit nr,从1变为0,或是从0变为1;返回该位的老值

2.3 锁

linux中常见的锁的分类

2.2.1 自旋锁

具体实现

简单地说就是无法获得锁时,不会休眠,会一直循环等待

CPU实现
多CPU使用原子操作实现
单CPU禁止别的进程调度(禁止抢占)
函数名作用
spin_lock_init(_lock)初始化自旋锁为unlock状态
void spin_lock(spinlock_t *lock)获取自旋锁(加锁),返回后肯定获得了锁
int spin_trylock(spinlock_t *lock)尝试获得自旋锁,成功获得锁则返回1,否则返回0
void spin_unlock(spinlock_t *lock)释放自旋锁,或称解锁
int spin_is_locked(spinlock_t *lock)返回自旋锁的状态,已加锁返回1,否则返回0

2.4 信号量

函数名作用
DEFINE_SEMAPHORE(name)定义一个struct semaphore name结构体,count值设置为1
void sema_init(struct semaphore *sem, int val)初始化semaphore
void down(struct semaphore *sem)获得信号量,如果暂时无法获得就会休眠,返回之后就表示肯定获得了信号量,在休眠过程中无法被唤醒,即使有信号发给这个进程也不处理
int down_interruptible(struct semaphore *sem)获得信号量,如果暂时无法获得就会休眠,休眠过程有可能收到信号而被唤醒,要判断返回值:0:获得了信号量 -EINTR:被信号打断
int down_killable(struct semaphore *sem)跟down_interruptible类似,down_interruptible可以被任意信号唤醒,但down_killable只能被“fatal signal”唤醒,返回值:0:获得了信量EINTR:被信号打断
int down_trylock(struct semaphore *sem)尝试获得信号量,不会休眠,返回值:0:获得了信号量1:没能获得信号量
int down_timeout(struct semaphore *sem, long jiffies)获得信号量,如果不成功,休眠一段时间返回值:0:获得了信号量-ETIME:这段时间内没能获取信号量,超时返回down_timeout休眠过程中,它不会被信号唤醒
void up(struct semaphore *sem)释放信号量,唤醒其他等待信号量的进程

2.5 互斥量/互斥体

函数名作用
mutex_init(mutex)初始化一个struct mutex指针 DEFINE_MUTEX(mutexname) 初始化struct mutex mutexname
int mutex_is_locked(struct mutex *lock)判断mutex的状态1:被锁了(locked)0:没有被锁
void mutex_lock(struct mutex *lock)获得mutex,如果暂时无法获得,休眠返回之时必定是已经获得了mutex
int mutex_lock_interruptible(struct mutex *lock)获得mutex,如果暂时无法获得,休眠;休眠过程中可以被信号唤醒,返回值:0:成功获得了mutex-EINTR:被信号唤醒了
int mutex_lock_killable(struct mutex *lock)跟mutex_lock_interruptible类似,mutex_lock_interruptible可以被任意信号唤醒,但mutex_lock_killable只能被“fatal signal”唤醒,返回值:0:获得了mutex-EINTR:被信号打断
int mutex_trylock(struct mutex *lock)尝试获取mutex,如果无法获得,不会休眠,返回值:1:获得了mutex,0:没有获得注意,这个返回值含义跟一般的mutex函数相反,
void mutex_unlock(struct mutex *lock)释放mutex,会唤醒其他等待同一个mutex的线程
int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock)让原子变量的值减1,如果减1后等于0,则获取mutex,返回值:1:原子变量等于0并且获得了mutex0:原子变量减1后并不等于0,没有获得mutex

3 何时用那种锁

何时用何种锁
举例简单介绍一下,上表中第一行“IRQ Handler A”和第一列“Softirq A”的交叉点是“spin_lock_irq()”,意思就是说如果“IRQ Handler A”和“Softirq A”要竞争临界资源,那么需要使用“spin_lock_irq()”函数。为什么不能用spin_lock而要用spin_lock_irq?也就是为什么要把中断给关掉?假设在Softirq A中获得了临界资源,这时发生了IRQ A中断,IRQ Handler A去尝试获得自旋锁,这就会导致死锁:所以需要关中断。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值