Linux併發控制

2021-10-01 11:49:10 字數 2697 閱讀 8537

目錄

併發和競態

編譯亂序和執行亂序

中斷遮蔽

原子操作

位原子操作

自旋鎖訊號量

互斥體完成量

1.併發是多個執行單元同時並行的執行。

2.競態是指併發操作對共享資源的訪問。競態的發生情況如下:

1.對稱多處理器(smp)的多個cpu的程序、中斷之間的併發為核間併發。

2.單個cpu內的多個程序併發訪問共享資源。

3.中斷與程序或者中斷與更高優先順序中斷之間。

1.編譯亂序是編譯器行為(如gcc的優化等級設定),可以對訪存指令進行亂序,減少邏輯上不必要的訪存,以盡量提高cache命中率和cpu的load/store單元的工作效率。

2.可以使用一下記憶體屏障解決編譯亂序的問題,保證記憶體屏障前後的指令不亂序。

a=b;

__asm__ __volatie__("": : :"memory");

c=d;

3.c中的volatile關鍵字更多的是避免記憶體訪問行為的合併,並不能用來阻止編譯器的編譯亂序問題。

4.執行亂序是處理器行為,編譯後的指令按照順序排放,但是在處理器執行時,後發射的指令還是可能先執行完,這是處理器的「亂序執行(out of order execution)」策略。連續位址的訪存指令可能會先執行,這樣快取命中率高。有的還允許訪存的非阻塞,即前一條訪存指令可能會應為未命中快取等因素造成長延時的儲存訪問,後面的訪存指令可以先執行,以方便從快取中取數。

5.亂序行為在單核的程式執行中是不可見的,因為單核cpu在碰到依賴點(後面的指令依賴於前面指令的執行結果)的時候會等待前面的指令完成,所以對於程式設計師是感覺不到的。但是對於smp處理器架構中,核與核之間的亂序是不存在依賴點關係的。這就需要引入記憶體屏障指令,解決多核間乙個核的記憶體行為對另乙個核可見的問題。

6.記憶體屏障指令,解決多核間乙個核的記憶體行為對另乙個核可見的問題。arm處理器的記憶體屏障指令為:

1.dmb(資料記憶體屏障),在dmb之後的顯示記憶體訪問執行前,保證所有在dmb指令之前的記憶體訪問完成。

2.dsb(資料同步屏障),等待所有在dsb指令之前的指令完成(包括此指令前的所有顯示記憶體訪問完成,位於此指令籤的所有快取,跳轉**核tlb維護操作全部完成)。

3.isb(指令同步屏障),flush流水線,是的所有isb之後執行的指令都是從快取或記憶體中獲得的。

疑義:是不是應該為作廢流水線,而不是flush,是isb之後指令重新從cache或記憶體獲取?

linux自旋鎖,互斥體等互斥邏輯需要用到上述指令。

6.雖然暫存器的訪問順序在cpu邏輯上構不成依賴關係,但是對於外設來說,暫存器的訪問順序可能是相互依賴的,例如比如先讀a暫存器再讀b暫存器才能獲取到b暫存器的值,a暫存器不讀的情況下讀b暫存器會返回無效值。這額時候也需要使用記憶體屏障指令。

1.原子操作可以保證對乙個整形資料的修改是排他性的。

2.對於arm處理器而言,底層使用ldrex和strex指令可以進行原子操作。

ldrex指令和strex指令是配對使用的,可以讓匯流排監控ldrex到strex之間有無其他實體訪問改位址

static inline void atomic_add(int i, atomic_t *v)

當strex執行失敗時,%1(tmp)暫存器裡的值為1,那麼就代表strex指令執行不成功,%0(result)暫存器裡的值並未成功載入到%3(v->counter)裡,那麼bne指令執行,再次進入ldrex指令。

1.自旋鎖是一種典型的對臨界資源進行互斥訪問的手段。

2.自旋鎖主要正對smp或單cpu但核心可搶占的情況。對單cpu和核心不支援搶占系統,自旋鎖退化為空操作。

3.自旋鎖是忙等鎖,鎖不可用時,cpu一直迴圈執行「測試並設定」該鎖直到該鎖可用而取得該鎖。cpu做的只是等待,所以一般用在時間極端的占用條件下。

4.自旋鎖可能導致系統死鎖,比如遞迴使用自旋鎖。

5.自選鎖定期間的臨界區**執行時,不能呼叫可能引起程序排程的函式。如cpoy_from_user,kmalloc/msleep等阻塞函式。可能引起核心的崩潰。

6.無論如何,中斷函式裡訪問臨界區也應該呼叫自旋鎖。

7.讀寫自旋鎖、順序鎖、讀-複製-更新。

1.訊號量是作業系統中最典型的用於同步和互斥的手段,訊號量的值可以試試0、1、n。訊號量與os中經典的pv操作對應。

2.乙個程序獲取訊號量,如果獲取不到訊號量則進入睡眠狀態;另乙個進行釋放訊號量並喚醒睡眠的程序,這樣獲取訊號量的程序就與釋放訊號量的程序進行了同步。

3.生產者消費者等關心具體數值的問題可以使用訊號量操作更加方便。

1.互斥體和自旋鎖使用的場合完全一樣,都是解決互斥問題的基本手段。

2.新的linux核心更傾向於直接使用mutex作為互斥手段,訊號量用作互斥不再被推薦使用。

3.互斥體和自旋鎖都是解決互斥問題的基本手段,但根據臨界區性質和系統特點,應當對這兩種方式進行取捨。

4.互斥體是程序級的,用於多個程序之間對資源的互斥,如果競爭失敗會發生程序上下文切換,當前程序進入睡眠狀態,其他程序執行。鑑於程序上下文切換的開銷也是很大的,所以資源占用時間較長時,採用互斥體是較好的選擇。

5.互斥體和自旋鎖選用三原則如下:

1.臨界區小使用自旋鎖,大使用互斥體。

2.臨界區內含有阻塞**,使用互斥體。

3.被保護的共享資源需要在中斷或者軟終端情況下使用,則只能使用自旋鎖或者使用互斥體的mutex_trylock()方式,避免阻塞。

linux併發控制

一.概念 1.併發 concurrency 指多個執行單元同時,並行被執行。2.併發的執行單元對共享資源,比如說,硬體資源,全域性變數,靜態變數等 訪問很容易導致競態 race conditions 舉個簡單事例,古代皇帝有很多妃子,皇帝第乙個時辰是宜妃的,第二個時辰是萱妃,最後時間是皇后的,這是原...

linux併發控制例子

例項篇 1.定義帶有裝置併發控制方案的結構體 諸如訊號量,自旋鎖等,反正前邊那麼多了 我是一名高手,告訴大家乙個高手的習慣,就是喜歡也習慣把將某裝置所使用的自旋鎖,訊號量等輔助手段也放到裝置結構體中,就像下邊這樣 struct csyncontrol dev 然後,將訊號量的初始化工作放到模組初始化...

linux 併發控制總結

atomic t atomic t atom atomic init 1 atomic dec and test atom atomic inc atom spin lock t spinlock t lock spin lock init lock define spinlock lock spi...