驱动并发控制笔记

来源:互联网 发布:网络用语cd是什么意思 编辑:程序博客网 时间:2024/05/15 10:19
 

控制临界区的访问的方法有:中断屏蔽,原子操作,自旋锁,和信号量等。

1.中断屏蔽

由于Linux系统的异步I/O,进程调度等很多重要操作都依赖于中断,中断对于内核的运行非常重要。长时间屏蔽中断是很危险的,有可能造成数据丢失甚至系统崩溃。

local_irq_disable(),local_irq_enable(),只能禁止和使能本CPU内的中断。单独使用中断屏蔽通常不是一种值得推荐的避免竞态的方法,它适宜与自旋锁联合使用。

local_irq_save(),local_irq_restore(),它们的作用相当于在local_irq_disable的基础上保存目前CPU中断位的信息。local_bh_disable,local_bh_enable,作用于中断的底半部。

2.原子操作

原子操作指的是在执行过程中不会被别的代码路径所中断的操作。原子量类似于在为进程的执行设置一道大门,钥匙就是原子量的加减。

整型原子

设置原子变量的值

void atomic_set(atomic_t *v,int i);

atomic_t v=ATOMIC_INIT(0);

获取原子变量的值

atomic_read(atomic_t *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);

操作并测试

int atomic_inc_and_test(atomic_t *v);

int atomic_dec_and_test(atomic_t *v);

int atomic_sub_and_test(atomic_t *v);

操作并返回

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);

位原子操作

设置位

void set_bit(nr,void *addr);

清除位

void clear_bit(nr,void *addr);

改变位

void change_bit(nr,void *addr);

测试位

test_bit(nr,void *addr);

测试并操作

int test_and_set_bit(nr,void *addr);

int test_and_clear_bit(nr,vid *addr);

int test_and_change_bit(nr,void *addr);

3.自旋锁

自旋锁底层依赖于原子操作

定义自旋锁

spinlock_t spin;

初始化自旋锁

spin_lock_init(lock);

获得自旋锁

spin_lock(lock);

spin_trylock(lock);

释放自旋锁

spin_unlock(lock);

自旋锁可以保证临界区不受别的CPU和本CPU内的抢占进程打扰,但是得到锁的代码路径在执行临界区的时候还可能受到中断和底半部的影响。

自旋锁与中断的结合

spin_lock_irq()

spin_unlock_irq()

spin_lock_irqsave()

spin_unlock_irqrestore()

spin_lock_bh()

spin_unlock_bh()

读写自旋锁

写操作最多一个进程,读方面可以有多个读执行单元。

定义和初始化读写自旋锁

rwlock_t my_rwlock = RW_LOCK_UNLOCKED(静态初始化)

rwlock_t my_rwlock;

rwlock_init(&my_rwlock);(动态初始化)

读锁定

void read_lock(rwlock_t *lock);

void read_lock_irqsave(rwlock_t *lock,unsigned long flags);

void read_lock_irq(rwlock_t *lock);

void read_lock_bh(rwlock_t *lock);

读解锁

void read_ulock(rwlock_t *lock);

void read_ulock_irqsave(rwlock_t *lock,unsigned long flags);

void read_ulock_irq(rwlock_t *lock);

void read_ulock_bh(rwlock_t *lock);

写锁定

void write_lock(rwlock_t *lock);

void write_lock_irqsave(rwlock_t *lock,unsigned long flags);

void write_lock_irq(rwlock_t *lock);

void write_lock_bh(rwlock_t *lock);

写解锁

void write_ulock(rwlock_t *lock);

void write_ulock_irqsave(rwlock_t *lock,unsigned long flags);

void write_ulock_irq(rwlock_t *lock);

void write_ulock_bh(rwlock_t *lock);

顺序锁

顺序锁是对读写锁的一种优化。读执行单元可以在写执行单元对顺序锁保护的共享资源进行写操作时仍然可以继续读,而不必等待写执行单元完成写操作。

4.信号量(见信号量学习笔记)

5.互斥体(见信号量学习笔记)

 

 

总结:在解决并发问题的机制中自旋锁和信号量的使用最为广泛。自旋锁会导致死循环,锁定期间不允许阻塞,要求锁定的临界区小。信号量允许临界区阻塞,可以适用于临界区大的情况。

原创粉丝点击