優先級翻轉與優先級繼承
優先級翻轉在可剝奪內核中是非常常見的,例子如下(H:High、M:Middle、L:Low)
任務 H 和任務 M 處于掛起狀態,等待某一事件的發生,任務 L 正在運行。
某一時刻任務 L 想要訪問共享資源,在此之前它必須先獲得對應該資源的信號量。
任務 L 獲得信號量并開始使用該共享資源。
由于任務 H 優先級高,它等待的事件發生后便剝奪了任務 L 的 CPU 使用權。
任務 H 開始運行。
任務 H 運行過程中也要使用任務 L 正在使用著的資源,由于該資源的信號量還被任務L 占用著,任務 H 只能進入掛起狀態,等待任務 L
釋放該信號量。
任務 L 繼續運行。
由于任務 M 的優先級高于任務 L,當任務 M 等待的事件發生后,任務 M 剝奪了任務L 的 CPU 使用權。
任務 M 處理該處理的事。
任務 M 執行完畢后,將 CPU 使用權歸還給任務 L。
任務 L 繼續運行。
最終任務 L 完成所有的工作并釋放了信號量,到此為止,由于實時內核知道有個高優先級的任務在等待這個信號量,故內核做任務切換。
任務 H 得到該信號量并接著運行。
在這種情況下,任務 H 的優先級實際上降到了任務 L 的優先級水平。因為任務 H 要一直等待直到任務 L 釋放其占用的那個共享資源。由于任務 M剝奪了任務 L 的 CPU 使用權,使得任務 H 的情況更加惡化,這樣就相當于任務 M 的優先級高于任務 H,導致優先級翻轉。
Linux 用 rt_mutex 來解決該問題,rt_mutex 是帶優先級繼承的互斥鎖。
當一個 rt_mutex 正在被一個低優先級的任務使用,而此時有個高優先級的任務也嘗試獲取這個 rt_mutex的話就會被阻塞。不過這個高優先級的任務會將低優先級任務的優先級提升到與自己相同的優先級,這就是優先級繼承。優先級繼承盡可能的降低了高優先級任務處于阻塞態的時間,并且將已經出現的“優先級翻轉”的影響降到最低。
優先級繼承并不能完全的消除優先級翻轉,它只是盡可能的降低優先級翻轉帶來的影響。
rt_mutex 不能用于中斷服務函數中,原因如下:
rt_mutex 有優先級繼承的機制,所以只能用在任務中,不能用于中斷服務函數。
中斷服務函數中不能因為要等待 rt_mutex 而設置阻塞時間進入阻塞態。
在 i2c_transfer 調用 __i2c_transfer 之前,就加了 rt_mutex,保證 I2C 傳輸盡快執行。
-
內核
+關注
關注
3文章
1375瀏覽量
40313 -
子系統
+關注
關注
0文章
109瀏覽量
12413 -
I2C
+關注
關注
28文章
1489瀏覽量
123962
發布評論請先 登錄
相關推薦
評論