并发与竞态

来源:互联网 发布:温州网络学堂登录 编辑:程序博客网 时间:2024/05/21 11:36

1 中断屏蔽

#include <linux/irqflags.h>local_irq_disable();local_irq_enable();local_irq_save(flags);local_irq_restore(flags);

2 原子操作

#include <asm/atomic.h>atomic_t v;//讲原子变量的值初始化为iv=ATOMIC_INIT(i);atomic_set(&v, i);atomic_read(v);//读取原子变量的值void atomic_add(int i, atomic_t *v);void atomic_sub(int i, atomic_t *v);void atomic_inc(atomic_t *v);void atomic_dec(atomic_t *v);atomic_sub_and_test(i, v);atomic_dec_and_test(v);atomic_inc_and_test(v);atomic_dec_return(v);atomic_inc_return(v); int atomic_add_negative(int i, atomic_t *v)

3 自旋锁

自旋锁在获取锁之前一直进入忙循环并重复检查锁是否被解锁,可用于不能休眠的流程中,例如中断处理等。拥有自旋锁时禁止中断;自旋锁拥有时间尽可能短;自旋锁下的执行函数不能休眠;1.普通自旋锁#include <linux/spinlock.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)spinlock_t  lock=SPIN_LOCK_UNLOCK;#elseDEFINE_SPINLOCK(lock);#endifspin_lock_init(&lock);void spin_lock(&lock);void  spin_lock_bh(&lock);//获取自旋锁之前禁止软件中断,但硬件中断保持打开void spin_lock_irq(&lock);//获取自旋锁之前禁止中断spin_lock_irqsave(&lock, flags);//获取自旋锁之前禁止中断,并将之前的中断状态保存在flags中void spin_unlock(&lock);void spin_unlock_bh(&lock);//释放自旋锁,并恢复软件中断void spin_unlock_irq(&lock);//释放自旋锁,并打开中断void spin_unlock_irqrestore(&lock, flags);//释放自旋锁,并将之前的中断状态恢复后打开中断非阻塞自旋锁获取:成功返回非零值,否则返回零int spin_trylock(&lock);int spin_trylock_bh(&lock);int spin_trylock_irq(&lock);2.读写自旋锁#include <linux/rwlock.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)rwlock_t lock=RW_LOCK_UNLOCK;#elseDEFINE_RWLOCK(lock);#endifrwlock_init(&lock);read_lock(&lock);read_lock_bh(&lock);//获取自旋锁之前禁止软件中断,但硬件中断保持打开read_lock_irq(&lock);//获取自旋锁之前禁止中断read_lock_irqsave(&lock, flags);//获取自旋锁之前禁止中断,并将之前的中断状态保存在flags中read_unlock(&lock);read_unlock_bh(&lock);//释放自旋锁,并恢复软件中断read_unlock_irq(&lock);//释放自旋锁,并打开中断read_unlock_irqrestore(&lock, flags);//释放自旋锁,并将之前的中断状态恢复后打开中断write_lock(&lock);write_lock_bh(&lock);//获取自旋锁之前禁止软件中断,但硬件中断保持打开write_lock_irq(&lock);//获取自旋锁之前禁止中断write_lock_irqsave(&lock, flags);//获取自旋锁之前禁止中断,并将之前的中断状态保存在flags中write_unlock(&lock);write_unlock_bh(&lock);//释放自旋锁,并恢复软件中断write_unlock_irq(&lock);//释放自旋锁,并打开中断write_unlock_irqrestore(&lock, flags);//释放自旋锁,并将之前的中断状态恢复后打开中断非阻塞自旋锁获取:成功返回非零值,否则返回零read_trylock(&lock);read_unlock_irqrestore(&lock, flags);write_trylock(&lock);

4 信号量

信号量在获取过程中会休眠,所以不能用于不能休眠的流程中,例如中断处理等。1.普通信号量#include <asm/semaphore.h>struct semaphore sem;初始化方式一:void sema_init(&sem,val);初始化方式二:#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)DECLARE_MUTEX(sem);#elseDEFINE_SEMAPHORE(sem);#endif初始化方式三://在2.6.25后该函数已被废除。请用sema_init(&sem,1);替代void init_MUTEX(&sem);void init_MUTEX_LOCKED(&sem);void down(&sem);//获取信号量int down_interruptible(&sem);//获取信号量,可被中断int down_trylock(&sem);//获取信号量,永不休眠void up(&sem);释放信号量2.读写信号量#include <linux/rwsem.h>struct rw_semaphore rw_sem;void init_rwsem(&rw_sem);void down_read(&rw_sem);//获取信号量int down_read_trylock(&rw_sem);//获取信号量,永不休眠void up_read(&rw_sem);释放信号量void down_write(&rw_sem);//获取信号量int down_write_trylock(&rw_sem);//获取信号量,永不休眠void up_write(&rw_sem);释放信号量void downgrade_write(&rw_sem);

5 互斥体

互斥体的使用方法和场景与信号量完全一样。#include <linux/mutex.h>struct mutex mux;mutex_init(mutex);void mutex_lock(struct mutex *lock);int __must_check mutex_lock_interruptible(struct mutex *lock);int mutex_trylock(struct mutex *lock);void mutex_unlock(struct mutex *lock);

6 completion

常用于进程、线程间同步#include <linux/completion.h>//不用声明,详细请查看头文件定义DECLARE_COMPLETION(comp);//动态创建和初始化struct completion comp;void init_completion(&comp);//等待完成void wait_for_completion(&comp);//触发完成void complete(&comp);void complete_all(&comp);

7 位操作

//定义:include/asm-generic/bitops/atomic.h#include <asm/bitops.h>//设置addr地址的第nr位void set_bit(int nr, volatile unsigned long *addr);//清除addr地址的第nr位void clear_bit(int nr, volatile unsigned long *addr);//切换addr地址的第nr位void change_bit(int nr, volatile unsigned long *addr);//设置addr地址的第nr位并返回这个位的先前值int test_and_set_bit(int nr, volatile unsigned long *addr);//清除addr地址的第nr位并返回这个位的先前值int test_and_clear_bit(int nr, volatile unsigned long *addr);//切换addr地址的第nr位并返回这个位的先前值int test_and_change_bit(int nr, volatile unsigned long *addr);

8 seqlock

#include <linux/seqlock.h>DEFINE_SEQLOCK(lock);seqlock_init(lock);//用于获取seqlock保护的资源的读取访问函数unsigned read_seqbegin(const seqlock_t *sl);//用于获取seqlock保护的资源的写入访问函数void write_seqlock(seqlock_t *sl);//用于释放seqlock保护的资源的写入访问函数void write_sequnlock(seqlock_t *sl);以上的读写函数还有很多变种,需要的请查看include/linux/seqlock.h文件

9 RCU(读取-复制-更新)

#include <linux/rcupdate.h>void rcu_read_unlock(void);void rcu_read_lock(void);void call_rcu(struct rcu_head *head,void (*func)(struct rcu_head *head));
0 0
原创粉丝点击