并发是多个执行单元同时 并行被执行。而并发的执行单元对共享资源(硬件资源和软件上的全局变量,静态变量)的访问很容易导致竞态。
主要的竞态有以下三种情况:对称多处理器(SMP)的多个CPU;单个CPU内进程与抢占它的进程;中断(硬中断,软中断,Tasklet 底半部)与进程之间。
注:上述情况,除了SMP是真正的并行之外,其他的都是“宏观并行,微观串行”,但其引发的问题和SMP相似。
解决竞态问题的途径是保证对共享资源的互斥访问,即:当一个进程访问的时候,其他的进程单元禁止访问。
访问共享资源的代码区称为临界区。访问临界区即需要加互斥机制。
实现互斥访问的途径有如下几种:
1 . 中断屏蔽
2 . 原子操作
3 . 自旋锁
4 . 信号量
1 . 中断屏蔽
CPU 一般都具备屏蔽中断和打开中断的功能,这使得正在执行的内核执行路径不被中断处理程序抢占,防止了竞态的放生
使用方法:
local_irq_disable()//屏蔽中断
。。。
critical section //临界区
。。。
local_irq_enable()//开启中断
2 . 原子操作
原子操作是指在执行的过程中不会被别的代码路径所中断的操作。
有两类函数可以实现原子操作:针对位 和针对整形变量的操作
整型原子操作:
1 设置原子变量的值
void atomic_set(atomic_t *v,int t);//设置值为i
atomic_t v= ATOMIC_INIT(0);//初始化
2 获取原子变量的值
atomic_read(atomic_t *v);
3 原子变量加/减
void atomic_add(atomic_t *v);
void atomic_sub(atomic_t *v);
4 原子变量自增/自减
void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);
5 操作并测试
int atomic_inc_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_sub_and_test(int i, atomic_t *v);
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);
位原子操作
1 设置位
void set_bit(nr,void *addr)
2 清除位
void clear_bit(nr,void *addr)
3 改变位
void change_bit(nr,void *addr)
4 测试位
void test_bit(nr,void *addr)
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);