亚洲综合图片区自拍_思思91精品国产综合在线观看_一区二区三区欧美_欧美黑人又粗又大_亚洲人成精品久久久久桥本

報(bào)道:Linux內(nèi)核鎖的那點(diǎn)事

2023-07-04 14:05:50 來源:嵌入式藝術(shù)

Linux設(shè)備驅(qū)動(dòng)中,我們必須要解決的一個(gè)問題是:多個(gè)進(jìn)程對(duì)共享資源的并發(fā)訪問,并發(fā)的訪問會(huì)導(dǎo)致競態(tài)。

1、并發(fā)和競態(tài)

并發(fā)(Concurrency):指的是多個(gè)執(zhí)行單元同時(shí)、并行的被執(zhí)行。


(相關(guān)資料圖)

競態(tài)(RaceConditions):并發(fā)執(zhí)行的單元對(duì)共享資源的訪問,容易導(dǎo)致競態(tài)。

共享資源:硬件資源和軟件上的全局變量、靜態(tài)變量等。

解決競態(tài)的途徑是:保證對(duì)共享資源的互斥訪問。

互斥訪問:一個(gè)執(zhí)行單元在訪問共享資源的時(shí)候,其他執(zhí)行單元被禁止訪問。

臨界區(qū)(Critical Sections):訪問共享資源的代碼區(qū)域成為臨界區(qū)。臨界區(qū)需要以某種互斥機(jī)制加以保護(hù)。

常見的互斥機(jī)制包括:中斷屏蔽,原子操作,自旋鎖,信號(hào)量,互斥體等。

2、競態(tài)發(fā)生的場合

image-20230511140139520

多對(duì)稱處理器(SMP)的多個(gè)CPU之間

多個(gè)CPU使用共同的系統(tǒng)總線,可以訪問共同的外設(shè)和存儲(chǔ)器。在SMP的情況下,多核(CPU0、CPU1)的競態(tài)可能發(fā)生于:

CPU0的進(jìn)程和CPU1的進(jìn)程之間CPU0的進(jìn)程和CPU1的中斷之間CPU0的中斷和CPU1的中斷之間單CPU內(nèi),該進(jìn)程與搶占它的進(jìn)程之間

在單CPU內(nèi),多個(gè)進(jìn)程并發(fā)執(zhí)行,當(dāng)一個(gè)進(jìn)程執(zhí)行的時(shí)間片耗盡,也有可能被另一個(gè)高優(yōu)先級(jí)進(jìn)程打斷,會(huì)發(fā)生競態(tài)。

中斷(軟中斷、硬中斷、Tasklet、底半部)與進(jìn)程之間

當(dāng)一個(gè)進(jìn)程正在執(zhí)行,一個(gè)外部/內(nèi)部中斷(軟中斷、硬中斷、Tasklet等)將其打斷,會(huì)導(dǎo)致競態(tài)發(fā)生。

3、編譯亂序和執(zhí)行亂序

除了并發(fā)訪問導(dǎo)致的競態(tài)外,還需要了解編譯器和處理器的一些特點(diǎn)所引發(fā)的一些問題。

3.1 編譯亂序

現(xiàn)代的高性能編譯器在目標(biāo)代碼優(yōu)化上都具有亂序優(yōu)化的能力,編譯器為了盡量 提高Cache命中率以及CPU的Load/Store單元的工作效率,可以對(duì)訪存的指令進(jìn)行亂序,減少邏輯上不必要的訪存。

因此,在打開編譯器優(yōu)化后,生成的匯編碼并沒有嚴(yán)格按照代碼的邏輯順序執(zhí)行,這是正常的。

為了解決編譯亂序的問題,可以加入barrier()編譯屏障,

該屏障可以阻擋編譯器的優(yōu)化。設(shè)置屏障的前后,可以保證執(zhí)行的語句不亂。

加入barrier()編譯屏障,即可保證正確的執(zhí)行順序。

例子:

#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;}

3.2 執(zhí)行亂序

編譯亂序是編譯器的行為,而執(zhí)行亂序就是處理器運(yùn)行時(shí)的行為。

高級(jí)的CPU往往會(huì)根據(jù)自身的緩存特性,將訪存指令重新排序執(zhí)行!這樣就導(dǎo)致了多個(gè)順序的指令,后發(fā)的指令仍有可能先執(zhí)行完畢。

這種執(zhí)行亂序,在多個(gè)CPU之間,以及單個(gè)CPU內(nèi)部,都是非常常見的。

3.2.1 多CPU之間

處理器為了解決多核之間,一個(gè)CPU的行為對(duì)另一個(gè)CPU可見的情況,ARM處理器引入了內(nèi)存屏障指令:

DMB(數(shù)據(jù)內(nèi)存屏障),保證在該指令前的所有指令,內(nèi)存訪問完成,再去訪問該指令之后的訪存動(dòng)作DSB(數(shù)據(jù)同步屏障),保證在該指令前的所有訪存指令執(zhí)行完畢(訪存,緩存,跳轉(zhuǎn)預(yù)測,TLB維護(hù)等)完成ISB(指令同步屏障),Flush流水線,保證所有在ISB之后執(zhí)行的指令都是從緩存或者內(nèi)存中獲得。

3.2.2 單CPU內(nèi)部

在單CPU中,我們常遇到訪問外設(shè)寄存器時(shí),某些外設(shè)寄存器就對(duì)讀寫順序有很高的要求,為了避免執(zhí)行亂序的發(fā)生,這時(shí)候就需要CPU的一些內(nèi)存屏障指令了。

CPU內(nèi)部,為了解決這種問題,CPU提供了一些內(nèi)存屏障指令:

可以參考Documentation/memory-devices.txtDocumentation/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); })

writelwritel_relaxed的區(qū)別就在于有無屏障。

4、總結(jié)

由上文可知,為了解決

并發(fā)導(dǎo)致的競態(tài)問題高性能的編譯器編譯亂序問題高性能的CPU帶來的執(zhí)行亂序問題

CPUARM處理器提供的內(nèi)存屏障指令等,這也是內(nèi)核鎖存在的意義。

標(biāo)簽:

上一篇:Linux內(nèi)核中斷屏蔽的實(shí)現(xiàn)-世界熱推薦
下一篇:最后一頁