在嵌入式系統(tǒng)中,如果使用基于優(yōu)先級(jí)調(diào)度算法的RTOS,系統(tǒng)中可能發(fā)生優(yōu)先級(jí)反轉(zhuǎn)現(xiàn)象。優(yōu)先級(jí)反轉(zhuǎn)用來(lái)描述系統(tǒng)中高優(yōu)先級(jí)任務(wù)由于等待低優(yōu)先級(jí)任務(wù)完成才能繼續(xù)執(zhí)行的情景,通常發(fā)生在試圖獲取信號(hào)量使用權(quán)或共享資源時(shí)。優(yōu)先級(jí)反轉(zhuǎn)可能會(huì)導(dǎo)致嚴(yán)重的后果。在小型嵌入式系統(tǒng)設(shè)計(jì)中,我們需要考慮如何訪(fǎng)問(wèn)共享資源,避免資源競(jìng)爭(zhēng),防止優(yōu)先級(jí)反轉(zhuǎn)發(fā)生。
本文將介紹如何通過(guò)分析工具檢測(cè)OPENRTOS(FreeRTOS)應(yīng)用中的優(yōu)先級(jí)反轉(zhuǎn)現(xiàn)象,如何最小化優(yōu)先級(jí)反轉(zhuǎn)的影響,及如何在設(shè)計(jì)中避免優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題。
使用Tracealyzer工具檢測(cè)優(yōu)先級(jí)反轉(zhuǎn)現(xiàn)象
Tracealyzer是一個(gè)可視化分析工具,以圖形化的方式展示事件發(fā)生的序列。我們通過(guò)一個(gè)Percepio公司的示例說(shuō)明如何使用Tracealyzer檢測(cè)優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題。應(yīng)用中存在一個(gè)隨機(jī)復(fù)位問(wèn)題,在復(fù)位異常處理中設(shè)置斷點(diǎn),發(fā)現(xiàn)該問(wèn)題是由于看門(mén)狗定時(shí)器超時(shí)引起的,看門(mén)狗定時(shí)器應(yīng)該在一個(gè)周期運(yùn)行的高優(yōu)先任務(wù)中重置。
插入自定義Tracealyzer用戶(hù)事件幫助工程師獲得更大的能見(jiàn)度?!坝脩?hù)事件”類(lèi)似于經(jīng)典的“printf()”調(diào)用。在此示例中,在看門(mén)狗計(jì)時(shí)器被重置或超時(shí)位置添加用戶(hù)事件。用戶(hù)事件還支持?jǐn)?shù)據(jù)參數(shù),記錄重置之前的計(jì)時(shí)器值,以查看看門(mén)狗“margin”,即剩下的時(shí)間。捕獲結(jié)果如圖1所示。
圖1 用戶(hù)事件示例
從圖中我們可以看到SamplerTask任務(wù)正常運(yùn)行,但任務(wù)在最后一個(gè)執(zhí)行過(guò)程中沒(méi)有清除看門(mén)狗計(jì)時(shí)器,導(dǎo)致看門(mén)狗重置事件發(fā)生。SamplerTask為什么沒(méi)有復(fù)位看門(mén)狗定時(shí)器?在Tracealyzer中使能Kernel Service calls,查看任務(wù)當(dāng)前在執(zhí)行什么操作,捕獲結(jié)果如圖2所示。
圖2 系統(tǒng)服務(wù)調(diào)用示例
SamplerTask任務(wù)的最后一個(gè)動(dòng)作是調(diào)用OPENRTOS函數(shù)xQueueSend,將消息放入消息隊(duì)列中。注意,該標(biāo)簽顯示為紅色,表示xQueueSend 函數(shù)將阻塞任務(wù),任務(wù)阻塞導(dǎo)致看門(mén)狗定時(shí)器復(fù)位之前,任務(wù)切換至ServerTask,從而導(dǎo)致看門(mén)狗超時(shí),引起系統(tǒng)復(fù)位。
為什么xQueueSend阻塞了任務(wù)?雙擊此事件標(biāo)簽,打開(kāi)Object History視圖,顯示xQueueSend函數(shù)操作隊(duì)列“ControlQueue”的所有操作,如圖3所示。圖中最右邊一列展示了隊(duì)列存儲(chǔ)的消息??梢钥吹较㈥?duì)列已經(jīng)包含五個(gè)消息,隊(duì)列已滿(mǎn),因此xQueueSend操作引起任務(wù)阻塞。但ControlTask任務(wù)應(yīng)該讀取隊(duì)列數(shù)據(jù)并清空隊(duì)列緩沖區(qū),為什么預(yù)期的行為沒(méi)有發(fā)生?
圖3 Object history視圖
研究該問(wèn)題,分析看門(mén)狗的margin如何隨時(shí)間而變化。這些信息記錄在User Event Logging中,使用User Event Signal Plot,我們可以繪制看門(mén)狗margin隨時(shí)間的變化。在同一時(shí)間軸上添加CPU負(fù)載圖,我們可以看到任務(wù)執(zhí)行如何影響看門(mén)狗margin,如圖4所示。
圖4 User event Single slot視圖
在CPU負(fù)載圖中,我們可以看到跟蹤的后半部分,ServerTask執(zhí)行消耗了約一半的跟蹤時(shí)間,這似乎影響了看門(mén)狗的margin。ServerTask任務(wù)(亮綠色)比ControlTask任務(wù)(深綠色)優(yōu)先級(jí)高,所以當(dāng)ServerTask任務(wù)消耗更多CPU時(shí)間后,ControlTask任務(wù)得到的CPU減少。由于高優(yōu)先級(jí)的ServerTask任務(wù)占用了許多CPU時(shí)間,導(dǎo)致ControlTask無(wú)法及時(shí)讀取消息隊(duì)列中的數(shù)據(jù)。這是優(yōu)先反轉(zhuǎn)問(wèn)題的一個(gè)例子,SamplerTask任務(wù)被不相關(guān)的低優(yōu)先級(jí)任務(wù)阻塞。
解決方案
更改任務(wù)優(yōu)先級(jí)
一種解決辦法是改變優(yōu)先級(jí),使ControlTask任務(wù)的優(yōu)先級(jí)高于ServerTask。圖5顯示了交換兩個(gè)任務(wù)調(diào)度優(yōu)先級(jí)后的運(yùn)行結(jié)果。系統(tǒng)行為更穩(wěn)定。SamplerTask任務(wù)(紅色)的CPU負(fù)載穩(wěn)定在20%左右,其周期行為穩(wěn)定,看門(mén)狗margin為一條“線(xiàn)”,維持在10毫秒??撮T(mén)狗不會(huì)超時(shí)-問(wèn)題解決了!(注意:任務(wù)由于優(yōu)先級(jí)改變,對(duì)應(yīng)的顯示顏色也發(fā)生了變化)。
圖5 交換ServerTask與ControlTask優(yōu)先級(jí)結(jié)果
使用互斥信號(hào)量
當(dāng)多個(gè)任務(wù)訪(fǎng)問(wèn)同一資源時(shí),例如網(wǎng)絡(luò)驅(qū)動(dòng)或圖形顯示,可能會(huì)發(fā)生優(yōu)先級(jí)反轉(zhuǎn)。這種情況下,可以使用互斥信號(hào)量降低優(yōu)先級(jí)反轉(zhuǎn)的影響。
互斥信號(hào)量是包含優(yōu)先級(jí)繼承機(jī)制的二值信號(hào)量,二值信號(hào)量更適合實(shí)現(xiàn)任務(wù)間或任務(wù)與中斷服務(wù)之間的同步操作,互斥信號(hào)量更適用于互斥實(shí)現(xiàn)。
用作互斥機(jī)制時(shí),互斥信號(hào)量相當(dāng)于一個(gè)令牌,保護(hù)共享資源。當(dāng)任務(wù)希望訪(fǎng)問(wèn)該共享資源時(shí),需要首先獲得(“take”)令牌。資源使用完后,任務(wù)必須釋放令牌,讓其它任務(wù)可以訪(fǎng)問(wèn)相同的資源。
互斥信號(hào)量允許指定阻塞時(shí)間,阻塞時(shí)間指示一個(gè)任務(wù)在嘗試獲取令牌時(shí),如果令牌不可用,任務(wù)可以阻塞的最大節(jié)拍數(shù)。然而,與二值信號(hào)量的區(qū)別在于,互斥量支持優(yōu)先級(jí)繼承機(jī)制。這意味著,如果有一個(gè)高優(yōu)先級(jí)的任務(wù)在試圖獲取當(dāng)前持有令牌的低優(yōu)先級(jí)任務(wù)占用的資源時(shí),系統(tǒng)會(huì)臨時(shí)提升占有資源的任務(wù)優(yōu)先級(jí)別為被阻塞任務(wù)的優(yōu)先級(jí)。該機(jī)制確保高優(yōu)先級(jí)的阻塞時(shí)間盡量短,從而盡量減少優(yōu)先級(jí)反轉(zhuǎn)的時(shí)間。
優(yōu)先級(jí)繼承并不能解決優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題,它只是最小化了反轉(zhuǎn)在某些情況下產(chǎn)生的影響。硬實(shí)時(shí)應(yīng)用設(shè)計(jì)時(shí),需保證優(yōu)先級(jí)反轉(zhuǎn)不會(huì)發(fā)生。
使用Gatekeeper任務(wù)
在訪(fǎng)問(wèn)系統(tǒng)資源時(shí),為了避免優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題,我們推薦使用“Gatekeeper”任務(wù)。Gatekeeper任務(wù)結(jié)構(gòu)如圖6所示,包含一個(gè)控制資源的任務(wù),接收數(shù)據(jù)/命令的隊(duì)列和一個(gè)回調(diào)函數(shù)。
應(yīng)用任務(wù)不直接訪(fǎng)問(wèn)資源,而是將數(shù)據(jù)/命令寫(xiě)入隊(duì)列。Gatekeeper任務(wù)處理接收到的數(shù)據(jù)/命令,并相應(yīng)地更新資源。資源狀態(tài)發(fā)生改變時(shí),將觸發(fā)ISR (例如接收到一個(gè)新的網(wǎng)絡(luò)消息),將信息放置在隊(duì)列中,然后,Gatekeeper任務(wù)將執(zhí)行回調(diào)函數(shù),將新的數(shù)據(jù)傳給應(yīng)用任務(wù)。
此方法防止了系統(tǒng)資源訪(fǎng)問(wèn)時(shí)優(yōu)先級(jí)反轉(zhuǎn)的出現(xiàn),是我們推薦的解決辦法。
圖6 Gatekeeper任務(wù)
結(jié)論
使用實(shí)時(shí)內(nèi)核,優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題是實(shí)時(shí)系統(tǒng)中出現(xiàn)得非常多的問(wèn)題。在嵌入式系統(tǒng)系統(tǒng)設(shè)計(jì)時(shí),應(yīng)盡量避免優(yōu)先級(jí)反轉(zhuǎn)發(fā)生,或者可以通過(guò)可視化分析工具捕獲該問(wèn)題,通過(guò)相應(yīng)的RTOS方法降低其風(fēng)險(xiǎn)。
審核編輯:湯梓紅
評(píng)論