一、并发与竞态
1、中断屏蔽
1.1中断屏蔽使用方法
local_irq_disable() //屏蔽中断
.........
critical section //临界区
.........
local_irq_enable() //开中断
----------------------------------------
local_irq_save(flags) //除屏蔽中断外,还能保存目前CPU的中断信息
local_irq_restore(flags) //与上行相反的操作
----------------------------------------
local_bh_disable() //禁止中断的低半部
local_bh_enable() //使能中断的低半部
说明:上面方法只能禁止和使能本CPU内的中断,不能解决SMP多CPU引发的竟态;
2、原子操作
2.1整形原子操作
2.1.1 设置原子变量的值
void atomic_set(atomic_t *v, int i); //设置原子变量的值为i
atomic_t v = ATOMIC_INIT(0); //定义原子变量V,并初始化为0
2.1.2 获取原子变量的值
atomic_read(atomic_t *v); //返回原子变量的值
2.1.3 原子变量加减
void atomic_add(int i, atomic_t *v); //原子变量加
void atomic_sub(int i, atomic_t *v); //原子变量减
2.1.4 原子变量自增、自减
void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);
2.1.5 操作并测试
void atomic_inc_and_test(atomic_t *v);
void atomic_dec_and_test(atomic_t *v);
void atomic_sub_test_(int i, atomic_t *v);
2.1.6 操作并返回
int atomic_add_return(int i, atomic_t *v);
int atomic_sub_return(int i, atomic_t *v);
int atomic_inc_return(atomic_t *v);
int atomic_dec_return(atomic_t *v);
2.2位原子操作
2.2.1 设置位
void set_bit(nr, void *addr); //设置addr的第nr位,即将该位写1
2.2.2 清除位
void clear_bit(nr, void *addr); //清除addr的第nr位,即将该位写0
2.2.3 改变位
void change_bit(nr, void *addr); //对addr的第nr位进行反置
2.2.4 测试位
test_bit(nr, void *addr); //返回addr地址的第nr位
2.2.5 测试并操作
int test_and_set_bit(nr, void *addr); //
int test_and_clear_bit(nr, void *addr);
int test_and_change_bit(nr, void *addr);
3、自旋锁【获取不到锁时将在原地打转,占用CPU资源,用于SMP CPU、多任务,被锁临界区小,备注:一般用自旋锁解决多CPU】
3.1 自旋锁的使用
3.1.1 定义自旋锁
spinlock_t spin;
3.1.2 初始化自旋锁
spin_lock_init(lock);
3.1.3 获得自旋锁
spin_lock(lock); //在原地打转
spin_try_lock(lock); //获得锁就返回真,否则就返回假,不在原地打转
3.1.4 释放自旋锁
spin_unlock(lock); //释放自旋锁
虽然自旋锁可以保证临界区不受别的CPU和本CPU内的抢占进程打扰,但是得到锁的代码容易受到中断和低半部(BH)的影响,所以的到自旋锁衍生;
3.1.5 获得自旋锁、禁止中断
spin_lock_irq() = spin_lock() + local_irq_disable();
3.1.6 释放自旋锁、释放中断
spin_unlock_irq() = spin_unlock() + local_irq_enable();
3.1.7 获得自旋锁、保存中断标识
spin_lock_irqsave() = spin_lock() + local_irq_save();
3.1.8 释放自旋锁、还原中断标识
spin_unlock_irqrestore() = spin_unlock() + local_irq_restore();
3.1.9 获得自旋锁、禁止低半部
spin_lock_hb() = spin_lock() + local_bh_disable();
3.1.10 释放自旋锁、使能低半部
spin_unlock_hb() = spin_unlock() + local_bh_enable();
3.2 读写自旋锁
3.2.1 定义和初始化读写自旋锁
rwlock_t my_rwlock = RW_LOCK_UNLOCKED; //静态初始化
rwlock_t my_rwlock;
rwlock_init(&my_rwlock); //动态初始化
3.2.2 读锁定
void read_lock(rwlock_t * lock);
void read_lock_irqsave(rwlock_t *lock, unsigned long flags);
void read_lcok_irq(rwlock_t * lock);
void read_lcok_bh(rwlock_t * lock);
3.2.3 读解锁
void read_unlock(rwlock_t * lock);
void read_unlock_irqsave(rwlock_t *lock, unsigned long flags);
void read_unlcok_irq(rwlock_t * lock);
void read_unlcok_bh(rwlock_t * lock);
3.2.2 写锁定
void write_lock(rwlock_t * lock);
void write_lock_irqsave(rwlock_t *lock, unsigned long flags);
void write_lcok_irq(rwlock_t * lock);
void write_lcok_bh(rwlock_t * lock);
3.2.5 写解锁
void write_unlock(rwlock_t * lock);
void write_unlock_irqsave(rwlock_t *lock, unsigned long flags);
void write_unlcok_irq(rwlock_t * lock);
void write_unlcok_bh(rwlock_t * lock);
3.3 顺序锁
3.3.1 获得顺序锁
void write_seqlock(seqlock_t *sl);
int write_tryseqlock(seqlock_t *sl);
void write_seqlock_irqsave(seqlock_t *sl, flags);
int write_seqlock_irq(seqlock_t *sl);
int write_seqlock_bh(seqlock_t *sl);
3.3.2 释放顺序锁
void write_sequnlock(seqlock_t *sl);
int write_trysequnlock(seqlock_t *sl);
void write_sequnlock_irqsave(seqlock_t *sl, flags);
int write_sequnlock_irq(seqlock_t *sl);
int write_sequnlock_bh(seqlock_t *sl);
4、信号量【获取不到锁时将进入休眠,不占用CPU资源, 用于SMP CPU、多任务,被锁临界区大,备注:用于多个进程之间对资源的互斥】
4.1 信号量的使用
4.1.1 定义信号量
struct semaphore sem;
4.1.2 初始化信号量
void sema_init(struct semaphore *sem, int val); //初始化信号量,并设置信号量的值为val
void init_MUTEX(struct semaphore *sem); //初始化信号量,并设置信号量为1
void init_MUTEX_LOCKED(struct semaphore *sem); //初始化信号量,并设置信号量为0
下面是定义并初始化信号量的“快捷方式”
DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name);
4.1.3 获得信号量
void down(struct semaphore *sem); //该函数用于获得信号量,会导致休眠,不能用于中断上下文
int down_interruptible(struct semaphore *sem); //该函数用于获得信号量,会导致休眠,可以中断
int down_trylock(struct semaphore *sem);
4.1.4 释放信号量
void up(struct semaphore *sem);
4.1.5 读写信号量
4.1.5.1 定义和初始化读写信号量
struct rw_semaphore my_rws; //定义信号量
void init_rwsem(struct rw_semaphore *sem); //初始化信号量
4.1.5.2 读信号量获取
void down_read(struct rw_semaphore *sem);
int down_read_trylock(struct rw_semaphore *sem);
4.1.5.3 读信号量释放
void up_read(struct rw_semaphore *sem);
4.1.5.4 写信号量获取
void down_write(struct rw_semaphore *sem);
int down_write_trylock(struct rw_semaphore *sem);
4.1.5.5 写信号量释放
void up_write(struct rw_semaphore *sem);
5、完成量用于同步【比信号量更好的同步机制】
6、互斥体
6.1 定义并初始化
struct mutex my_mutex;
mutex_init(&my_mutex);
6.2 获取互斥体
void fastcall mutex_lock(struct mutex *lock);
void fastcall mutex_lock_interruptible(struct mutex *lock);
void fastcall mutex_trylock(struct mutex *lock);
6.3 释放互斥体
void fastcall mutex_unlock(struct mutex *lock);
linux驱动之并发与竟态
原创
©著作权归作者所有:来自51CTO博客作者JDSH0224的原创作品,请联系作者获取转载授权,否则将追究法律责任
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
Linux驱动开发之杂项设备注册和Linux2.6设备注册
Linux设备驱动开发中,需要向内核正确注册设备,才能创建设备节点,以供应用层访问。本文将详细介绍Linux下的两种设备注册方法:杂项设备注册和Linux 2.6新方法注册。
Linux驱动开发 杂项设备注册 Linux2.6设备注册 例程分享 相关API -
Linux驱动开发|Linux并发与竞争
Linux并发与竞争
驱动开发 linux lock spinlock semaphore -
ldd3学习之五:并发与竞态
对并发的管理是操作系统编程中核心的问题之一。并发产生竞态,竞态导
信号量 自旋锁 初始化 -
Linux驱动开发——并发和竞态(自旋锁方式的使用③)
文章目录解决竞态引起异常的方法之自旋锁解决竞态引起异常的方法之自旋锁
自旋锁 #include 临界区 linux 初始化 -
并发与竞态 (自旋锁)
简介自旋锁: 它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资
自旋锁 加锁 临界区 #endif 互斥锁 -
Linux驱动开发——并发和竞态(中断屏蔽方式的使用②)
文章目录
中断屏蔽 临界区 #include 多核 linux