臨界區未保護出現的異常
今天我們說說其中之一的原因:臨界資源未保護。
我們先看個例子,假如有乙個5個節點單向鍊錶,如下結構:
head->1->2->3->4->5->null
有一任務a在乙個單向鍊錶的2->3節點之間插入乙個新的2a節點,已經將2->2a,還未將2a->3,此時,鍊錶變為兩個未完整的部分,如下結構:
head->1->2->2a->?
3->4->5->null
如此時,任務a被更高優先順序的任務b搶占了,並任務b開始訪問該鍊錶,那麼任務b此次訪問就會獲得乙個錯誤的結果。
上面的情景就是臨界資源未保護導致錯誤的一種情況,解決這類問題我們通常有兩種方法,一種是互斥鎖保護,一種是暫時遮蔽中斷。
借助這個例子我們先了解幾個與臨界資源保護相關的概念。
相關概念
臨界資源
臨界資源指會被多個任務(或中斷)訪問到的公共資源。包含軟體資源和硬體資源,軟體資源指全域性變數,如上面例子中的鍊錶,也可能是乙個整型數。硬體資源指硬體相關的資源,如spi,i2c匯流排等。臨界資源的訪問是需要保證完整的,否則就會出現錯誤的結果。為了描述方便,下文**現的『任務』同時指代任務和中斷。
臨界區
會訪問臨界資源的**片段,在上面的例子中就是指對鍊錶進行增刪改查的**片段,或對硬體匯流排的訪問的**片段。
可重入
某個函式在執行時可被其他任務打斷再次進入執行的函式或**片段。根據重入性質可將函式分為以下三種型別。
函式(**段)型別
是否引用臨界資源
是否保護
例子不可重入有無
暫無任務(執行緒)安全有有
xtasknotifygive(freertos任務通知函式)
可重入無
/memcpy
臨界區保護
通過某種互斥手段保護臨界區**不會被打斷及重入,比如遮蔽會引用臨界資源的中斷,或者進入臨界區前先獲取互斥鎖,操作未完成前其他任務無法進入。
臨界資源保護
這個好理解,就是保護共享資源的完整性訪問,防止出現不完整的資料,乙個臨界資源的通常具有幾個臨界區。比如乙個鍊錶具有增、刪、改、查四個介面,就具有四個臨界區,當採用互斥鎖(或訊號量等)作為保護手段時,同乙個臨界資源必須使用同乙個互斥鎖物件進行保護。
如何判斷採用何種保護型別
下表中例舉了當前任務被其他任務搶占時的不同場景及應該使用何種互斥方式。
當前任務型別
搶占任務型別
保護方式/任務
任務互斥鎖 或 遮蔽中斷
任務中斷及任務
遮蔽中斷
中斷中斷
遮蔽中斷
總的來說,臨界區的保護有互斥鎖和遮蔽中斷兩種型別,採用互斥鎖需要更多資源,但是可提高的系統的實時性,遮蔽中斷需要的資源更少,但是會影響系統的實時性。
如何減少臨界資源保護的情形出現
將公共變數盡可能定義為static
僅將必要的對外介面定義為extern,其他介面都定義為static
確認extern介面是否需要進行臨界區保護並依據需要執行
如何檢查專案中是否存在未進行保護的臨界區
找出臨界資源
查詢所有引用該資源的**
檢查每個**片段是否進行了必要的保護
基礎資料型別的臨界區保護
前面描述的臨界資源主要是指復合資料型別,如結構體、鍊錶、i2c匯流排等。如果臨界資源是基本資料型別的話,不一定每個引用的**片段都需要進行保護的,如對乙個整型數的讀取是不需要進行保護的,因為讀取乙個整形數隻需乙個時鐘週期即可完成,不存在被打斷的情況,乙個時鐘週期已經是cpu的最小執行單位了。對基本資料型別的寫操作也不一定需要進行保護,如freertos中掛起所有任務的函式就沒有進行保護:
void vtasksuspendall( void )
因為即使被打斷,並高優先順序任務會訪問該變數,那也會是一次「零和訪問」。即高階任務訪問結束後該變數的值還是會與打斷低階任務時的值時一樣的,也就是高階任務對該變數的所有操作的和為零。在freertos中vtasksuspendall和xtaskresumeall是成對訪問的,乙個執行++,乙個執行- -,和為0。
哪種情況需要進行保護呢? 非「零和訪問」操作就需要保護,實際應用場景中的多數是非「零和訪問」的,基礎型別的保護手段比復合型別的多一種,這種方式叫原子操作。原子操作時由晶元指令支援的操作,可確保一次「讀-改-寫」過程不會被打斷,如armv6(cortex-m3核使用的armv7-m架構是支援的)及以上就提供了ldrex和strex這對指令來實現原子操作,當cpu執行了ldrex從記憶體載入暫存器後該記憶體位址就被標記為獨佔狀態,直到執行了strex指令將資料存回記憶體中。
三 FreeRTOS 臨界段的保護
3.4 開中斷 3.5 進入臨界段 3.6 退出臨界段 3.7 案例 野火 freertos 核心實現與應用開發實戰 基於stm32 臨界段用一句話概括就是一段在執行的時候不能被中斷的 段。在 freertos 裡面,這個臨界段最常出現的就是對全域性變數的操作,全域性變數就好像是乙個槍把子,誰都可以...
FreeRTOS 臨界區總結
當一名嵌入式開發人員從裸機開發切換到 基於 freertos 的開發後就要注意 中斷,資源競爭等等問題了。下面,總結一下 freertos 臨界區的知識及用法 1.應用程式使用臨界區 1.1 深入剖析的方法 1.2 使用方法 2.中斷函式中臨界區 2.1 深入剖析的方法 2.2 使用方法 void ...
FreeRTOS臨界區操作
進入臨界保護 支援巢狀 taskenter critical 退出臨界保護 支援巢狀 taskexit critical 中斷裡進入臨界保護 支援巢狀 taskenter critical from isr 中斷裡退出臨界保護 支援巢狀 taskexit critical from isr x 進入...