並發是多個執行單元同時 並行被執行。而並發的執行單元對共享資源(硬件資源和軟件上的全局變量,靜態變量)的訪問很容易導致競態。
主要的競態有以下三種情況:對稱多處理器(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);