您好,登錄后才能下訂單哦!
一個高優先級線程通過信號量機制訪問共享資源時,該信號量已被一個低優先級線程占有,而這個低優先級線程在訪問共享資源時被其他的一些中等優先級線程搶占,因此造成高優先級線程被許多具有較低優先級的線程阻塞,稱此現象為優先級反轉。
優先級反轉會導致低優先級任務先于高優先級任務運行,在實時系統中會導致不可控的現象發生,因此,優先級反轉在實時系統中是不可接受的。
高優先級任務不能執行的原因是因為低優先級占用了資源,而低優先級不能獲得CPU,無法釋放資源,所以解決優先級反轉的原則是讓低優先級任務盡快執行,釋放資源。
SylixOS下解決優先級反轉有優先級天花板策略(priority ceiling)和優先級繼承策略(priority inheritance),且SylixOS下互斥信號量同時支持這兩種策略。
優先級天花板策略是指將占有某資源的任務的優先級提高,提升到可能訪問該資源的所有任務中最高優先級任務的優先級(這個優先級稱為該資源的優先級天花板)。
當發現高優先級的任務因為低優先級任務占用資源而阻塞時,就將低優先級任務的優先級提升到等待它所占有的資源的最高優先級任務的優先級。
互斥量在創建時,需先創建互斥量屬性塊,SylixOS下互斥量屬性塊結構如程序清單 3.1所示。
程序清單 3.1 互斥量屬性塊結構
typedef struct { int PMUTEXATTR_iIsEnable; /* 此屬性塊是否有效 */ int PMUTEXATTR_iType; /* 互斥量類型 */ int PMUTEXATTR_iPrioceiling; /* 天花板優先級 */ unsigned long PMUTEXATTR_ulOption; /* 算法類型 */ } pthread_mutexattr_t;
初始化互斥量時,如果不為互斥量屬性塊進行初始化,則使用默認屬性,SylixOS互斥量默認屬性塊如程序清單 3.2所示。
程序清單 3.2 默認互斥量屬性塊
static const pthread_mutexattr_t _G_pmutexattrDefault = { 1, PTHREAD_MUTEX_DEFAULT, /* 允許遞歸調用 */ PTHREAD_MUTEX_CEILING, (LW_OPTION_INHERIT_PRIORITY | LW_OPTION_WAIT_PRIORITY) /*PTHREAD_PRIO_NONE */ };
由默認互斥量默認屬性塊可知,SylixOS下默認解決優先級反轉方案是優先級繼承策略。
低優先級的任務占有資源,且高任務的優先級請求資源時,會嘗試提高低優先級任務的優先級,在申請資源時調用_EventPrioTryBoost函數嘗試提高任務優先級。
#include <SylixOS.h> VOID _EventPrioTryBoost (PLW_CLASS_EVENT pevent, PLW_CLASS_TCB ptcbCur)
函數_EventPrioTryBoost原型分析:
參數pevent為資源所屬的事件控制塊;
參數ptcbCur為當前任務控制塊。
該函數根據互斥量屬性塊的屬性設置,確定選用優先級繼承策略或者天花板策略(SylixOS下默認是使用優先級繼承策略),調用_SchedSetPrio函數改變任務的優先級。
低優先級任務釋放互斥量時,調用EventPrioTryResume嘗試恢復任務的優先級。
#include <SylixOS.h> VOID _EventPrioTryResume (PLW_CLASS_EVENT pevent, PLW_CLASS_TCB ptcbCur)
函數_EventPrioTryResume原型分析:
參數pevent為資源所屬的事件控制塊;
參數ptcbCur為當前任務控制塊。
低優先級任務刪除互斥量時,會嘗試恢復任務優先級,代碼片段如程序清單 3.3所示。
程序清單 3.3 嘗試恢復優先級
if (ptcb) { ucPriority = (UINT8)pevent->EVENT_ulMaxCounter; /* 獲得原線程優先級 */ /* * 擁有者優先級發生了變化,還原優先級 */ if (!LW_PRIO_IS_EQU(ucPriority, ptcb->TCB_ucPriority)) { _SchedSetPrio(ptcb, ucPriority); } }
在使用互斥量時,嘗試提高或恢復任務優先級,調用SchedSetPrio函數進行優先級設置。
#include <SylixOS.h> VOID _SchedSetPrio (PLW_CLASS_TCB ptcb, UINT8 ucPriority)
函數_SchedSetPrio原型分析:
參數ptcb為當前任務控制塊;
參數ucPriority為需設置的優先級。
_SchedSetPrio函數改變任務的優先級,實現流程如圖 4.1所示。
圖 4.1 優先級設置流程
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。