
在Linux設備驅動中,我們必須要解決的一個問題是:多個進程對共享資源的并發訪問,并發的訪問會導致競態。
?
并發(Concurrency):指的是多個執行單元同時、并行的被執行。
競態(RaceConditions):并發執行的單元對共享資源的訪問,容易導致競態。
共享資源:硬件資源和軟件上的全局變量、靜態變量等。
?
解決競態的途徑是:保證對共享資源的互斥訪問。
互斥訪問:一個執行單元在訪問共享資源的時候,其他執行單元被禁止訪問。
臨界區(Critical Sections):訪問共享資源的代碼區域成為臨界區。臨界區需要以某種互斥機制加以保護。
常見的互斥機制包括:中斷屏蔽,原子操作,自旋鎖,信號量,互斥體等。
?

多個CPU使用共同的系統總線,可以訪問共同的外設和存儲器。在SMP的情況下,多核(CPU0、CPU1)的競態可能發生于:
CPU0的進程和CPU1的進程之間CPU0的進程和CPU1的中斷之間CPU0的中斷和CPU1的中斷之間?
在單CPU內,多個進程并發執行,當一個進程執行的時間片耗盡,也有可能被另一個高優先級進程打斷,會發生競態。
?
當一個進程正在執行,一個外部/內部中斷(軟中斷、硬中斷、Tasklet等)將其打斷,會導致競態發生。
?
除了并發訪問導致的競態外,還需要了解編譯器和處理器的一些特點所引發的一些問題。
現代的高性能編譯器在目標代碼優化上都具有亂序優化的能力,編譯器為了盡量提高Cache命中率以及CPU的Load/Store單元的工作效率,可以對訪存的指令進行亂序,減少邏輯上不必要的訪存。
因此,在打開編譯器優化后,生成的匯編碼并沒有嚴格按照代碼的邏輯順序執行,這是正常的。
為了解決編譯亂序的問題,可以加入barrier()編譯屏障,
該屏障可以阻擋編譯器的優化。設置屏障的前后,可以保證執行的語句不亂。
加入barrier()編譯屏障,即可保證正確的執行順序。
例子:
#define?barrier()?__asm__?__volatile__("":?:?:"memory")
int?main(int?argc,char?*argv[])
{
?int?a?=?0,b,c,d[4096],e;
?e?=?d[4095];
????barrier();
?b?=?a;
?c?=?a;
?return?0;
}
?
編譯亂序是編譯器的行為,而執行亂序就是處理器運行時的行為。
高級的CPU往往會根據自身的緩存特性,將訪存指令重新排序執行!這樣就導致了多個順序的指令,后發的指令仍有可能先執行完畢。
這種執行亂序,在多個
CPU之間,以及單個CPU內部,都是非常常見的。
處理器為了解決多核之間,一個CPU的行為對另一個CPU可見的情況,ARM處理器引入了內存屏障指令:
Flush流水線,保證所有在ISB之后執行的指令都是從緩存或者內存中獲得。?
在單
CPU中,我們常遇到訪問外設寄存器時,某些外設寄存器就對讀寫順序有很高的要求,為了避免執行亂序的發生,這時候就需要CPU的一些內存屏障指令了。
CPU內部,為了解決這種問題,CPU提供了一些內存屏障指令:
可以參考
Documentation/memory-devices.txt和Documentation/io_ordering.txt
mb()rmb()wmb()__iormb()____iowmb()__#define?writeb_relaxed(v,c)?__raw_writeb(v,c)
#define?writew_relaxed(v,c)?__raw_writew((__force?u16)?cpu_to_le16(v),c)
#define?writel_relaxed(v,c)?__raw_writel((__force?u32)?cpu_to_le32(v),c)
#define?readb(c)??({?u8??__v?=?readb_relaxed(c);?__iormb();?__v;?})
#define?readw(c)??({?u16?__v?=?readw_relaxed(c);?__iormb();?__v;?})
#define?readl(c)??({?u32?__v?=?readl_relaxed(c);?__iormb();?__v;?})
#define?writeb(v,c)??({?__iowmb();?writeb_relaxed(v,c);?})
#define?writew(v,c)??({?__iowmb();?writew_relaxed(v,c);?})
#define?writel(v,c)??({?__iowmb();?writel_relaxed(v,c);?})
writel與writel_relaxed的區別就在于有無屏障。
?
由上文可知,為了解決
CPU帶來的執行亂序問題CPU和ARM處理器提供的內存屏障指令等,這也是內核鎖存在的意義。

