正文
4.資源Resources
訪問需要在任務和ISR之間共享的硬件或數據可能是不可靠和不安全的。這是因為當較低優先級的任務或ISR正在更新共享數據時,可能會發生任務或ISR搶占。這種情況被稱為競態條件,非常難以測試。
訪問共享數據的語句序列稱為臨界區。為了提供對臨界區中引用的代碼和數據的安全訪問,需要強制互斥。換句話說,必須確保在臨界段期間,系統中沒有其他任務或二類中斷能夠搶占正在執行的任務。
在Task章節中,看到可以將任務聲明為非搶占式可以防止出現互斥問題。然而,這種方法是治標不治本的,因為它通過防止出現搶占來防止搶占帶來的問題。
操作系統提供基于資源的互斥機制。資源Resources只是一個二進制信號量。當一個任務或二類ISR獲得資源時,其他任務或ISR無法獲得該資源。這可以防止任何其他任務或ISR同時進入相同的臨界區。當臨界區結束時,任務或ISR釋放資源,另一個任務/ISR可以進入臨界區。
當高優先級任務被低優先級任務阻止執行時,這稱為優先級反轉,因為高優先級任務比低優先級任務需要更長的時間來完成它的執行。較低優先級的任務似乎優先于較高優先級的任務運行,這與實際優先級分配的預期相反。高優先級的任務被低優先級的任務阻塞。
由于優先級反轉會在系統中引入無界阻塞,二進制信號量在傳統操作系統中經常有不好的名聲。例如,如果低優先級任務阻止高優先級任務執行,但它本身被一個不需要訪問共享資源的中等優先級任務搶占,那么高優先級任務也將被中等優先級任務的執行阻塞。由于低優先級任務在持有共享資源時可能會被搶占多次,因此高優先級任務遭受的阻塞可能是無限的,如果需要確定任務響應所需的最長時間,則會帶來嚴重的問題。在極端情況下,任務可能會達到一種被稱為“死鎖”的狀態,在這種狀態下,每個任務都在等待進入一個臨界區,而這個臨界區正在被其他任務使用。
在AUTOSAR OS中,避免了通常與優先級反轉和死鎖相關的問題,因為資源是根據鎖定協議鎖定的。這個鎖協議稱為優先級上限協議(優先級天花板協議),特別是稱為立即繼承優先級上限協議(或堆棧資源協議)的版本。
優先級上限協議使用了優先級上限的概念。系統中的每個資源都被分配了一個上限優先級,該優先級等于需要訪問該資源的任何任務或ISR的最高優先級。當任務或ISR獲得資源時,任務/ISR的運行優先級將增加到資源的最高優先級(當且僅當該優先級高于任務/ISR當前的運行優先級)。當資源被釋放時,任務或ISR的優先級恢復到該任務或ISR發出呼叫之前的優先級。如圖4.1所示。
圖4.1 提升至最高優先級
立即繼承優先級上限協議提供了兩個主要優點:
1)優先級反轉被最小化。
每次高優先級任務或ISR準備就緒時,它的執行最多只能被一個已經持有資源的低優先級任務或ISR延遲一次。這意味著沒有累積阻塞,因此可以對任務遭受的阻塞設置上限-最大阻塞時間是低優先級任務/ISR持有共享資源的最長時間。此外,這種阻塞總是在執行開始時發生。這樣做的結果是,資源在需要鎖定時總是處于空閑狀態。在AUTOSAR操作系統中不需要等待資源被釋放。
2)它保證沒有死鎖。
一個任務或ISR必須在執行中才能產生鎖。假設一個任務(或ISR)試圖獲取資源。如果另一個任務或ISR已經擁有資源,那么由于該任務或ISR必須以最高優先級運行,因此發出請求的任務不會執行(它不會是系統中最高優先級的任務或ISR),因此不能嘗試鎖定資源。
4.1 配置資源Resource Configuration
在最基本的級別上,資源只需要命名和分配類型。AUTOSAR OS中有三種類型的資源:
1)標準資源Standard Resources是普通的操作系統信號量。配置標準資源將創建具有指定名稱的資源。
2)鏈接資源Linked Resources允許為標準(或另一個鏈接的)資源設置別名,以便可以對同一資源進行嵌套鎖定。這些將在第4.4節中詳細討論。
2)內部資源Internal Resources是在進入任務時自動鎖定并在任務結束時自動釋放的資源。這些將在第4.5節中詳細討論。
圖4.2:在rtaoscfg上配置資源
RTA-OS需要知道哪些任務和ISRs使用了哪些資源。然后,它可以計算優先級上限協議所使用的上限優先級。
#includeTASK(Task1) { ... GetResource(Resource1); /* Critical section. */ ReleaseResource(Resource1); ... TerminateTask(); }
Example 4.1: Using Resources
可以在任務或ISR配置期間配置每個任務或ISR的其他資源使用信息。
圖4.2顯示了已經聲明了一個名為Resource1的資源。在程序中引用此資源時,必須使用相同的名稱。
4.2 中斷級別的資源Resources on Interrupt Level
在AUTOSAR OS中,任務和中斷之間共享的資源是可選的。RTA-OS支持這個可選特性。
RTA-OS將自動識別組合資源,因此您不需要進行任何特殊配置。
當任務獲得與ISR共享的資源時,RTA-OS將屏蔽所有中斷,中斷優先級小于或等于共享資源的最高優先級中斷。
這只是優先級上限協議的擴展。在任務和ISR之間共享資源意味著提供了比啟用/禁用和暫停/恢復API調用更大的對內部中斷屏蔽的控制,因為它們可以將中斷子集屏蔽到特定的優先級級別。因此,當使用支持嵌套中斷的RTA-OS端口時,中斷級別的資源特別有用。
4.3 使用資源Using Resources
可以使用GetResource() API調用獲取資源。然后,您可以使用ReleaseResource()調用釋放資源。一個任務或ISR必須在釋放了它所鎖定的所有資源之后才能終止。
任務或ISR只能使用在RTA-OS配置過程中指定的資源。例4.1展示了如何在Task1中使用資源。
對GetResource()和ReleaseResource()的調用必須匹配。無法獲取已鎖定的資源。無法釋放尚未鎖定的資源。
圖4.3:執行具有資源鎖的任務
當執行GetResource()時,它將調用任務或ISR的優先級提升到資源的最高優先級。資源的上限優先級是共享該資源的所有任務或ISR的最高優先級,由RTA-OS自動計算。如果任何優先級低于上限優先級的任務準備好運行,那么它將被阻止執行(它將被阻塞),直到正在運行的任務的優先級恢復正常。
圖4.3通過以下配置顯示了此效果:
Task 2的第一次激活被阻塞,因為Task 1已經鎖定了R2。Task 2的第二次激活也被阻塞,但這次是因為Task 1鎖定了R1。Task 3的第一次激活同樣被阻塞,因為Task 1持有R1。當Task 1釋放R1時,操作系統運行優先級最高的就緒任務Task 3。在Task 3終止時,執行Task 2,最后,當Task 2終止時,繼續執行Task 1。
4.3.1 嵌套資源調用Nesting Resource Calls
可以同時獲得多個資源,但是API調用必須嚴格嵌套。我們來看兩個例子;一個顯示嵌套錯誤的調用,另一個顯示嵌套正確的API調用。
例4.2顯示Resource1和Resource2以錯誤的順序被釋放。
例4.3展示了一個正確嵌套的示例。所有的資源都被保留,然后按正確的順序釋放。
GetResource(Resource1); GetResource(Resource2); ReleaseResource(Resource1);/*Illegal!*/ /* You must release Resource2 before Resource1 */ ReleaseResource(Resource2);
Example 4.2: Illegal Nesting of Resource Calls
GetResource(Resource1); GetResource(Resource2); GetResource(Resource3); ReleaseResource(Resource3); ReleaseResource(Resource2); ReleaseResource(Resource1);
Example 4.3: Correctly Nested Resource Calls
4.4 鏈接資源Linked Resources
在AUTOSAR操作系統中,對相同資源的GetResource() API調用不能嵌套。但是,有時可能需要嵌套資源鎖。
應用程序可能使用在多個任務之間共享的函數。如果共享函數需要獲得一個任務使用的資源,而其他任務不需要,會發生什么情況?看一下例4.4。
#includevoid SomeFunction(void) { GetResource(Resource1); /* !!! Not allowed if caller is Task1 !!! */ ... ReleaseResource(Resource1); /* !!! Not allowed if caller is Task1 !!! */ } TASK(Task1) { GetResource(Resource1); /* Critical section. */ SomeFunction(); ReleaseResource(Resource1); } TASK(Task2) { SomeFunction(); }
Example 4.4: Illegal locking of previously locked resource
在這些情況下,(可能)持有的資源的嵌套必須使用鏈接的資源。鏈接資源是現有資源的別名,并保護相同的共享對象。
圖4.4顯示了如何使用rtaoscfg聲明鏈接的資源。
圖4.4:配置鏈接資源
使用鏈接的資源,例4.4將被重寫為例4.5所示。
#includevoid SomeFunction(void) { GetResource(LinkedToResource1); /* Okay */ ... ReleaseResource(LinkedToResource1); /* Okay */ } TASK(Task1) { GetResource(Resource1); /* Critical section. */ SomeFunction(); ReleaseResource(Resource1); } TASK(Task2) { SomeFunction(); }
Example 4.5: Using Linked Resources
鏈接的資源使用與標準資源相同的API調用來保持和釋放(這些將在4.3節中解釋)。
也可以創建鏈接資源到已有的鏈接資源。
4.5 內部資源Internal Resources
如果一組任務非常緊密地共享數據,那么就運行時成本而言,使用標準資源來保護對每個數據項的每次訪問可能過于昂貴。甚至可能無法確定需要保存資源的所有位置。
可以通過使用內部資源來防止對共享數據的并發訪問。內部資源是為任務的生命周期分配的資源。使用rtaoscfg離線配置內部資源。然而,與普通資源不同的是,無法獲取和釋放它們。
從概念上講,RTA-OS在啟動任務之前立即鎖定內部資源,并在任務結束后立即釋放資源。
當任務進入運行狀態時,RTA-OS中內部資源的實現不會產生運行時成本,因為rtaosgen會計算任務脫機運行的優先級,并按此優先級簡單地調度任務。共享內部資源的任務集在配置時使用rtaoscfg靜態定義。
注意:在AUTOSAR OS中,內部資源僅對任務可用。但是,也沒有理由不能由第一類和第二類ISR共享內部資源。RTA-OS提供了AUTOSAR OS的擴展,允許ISR使用內部資源。當任務鎖定與ISR共享的內部資源時,則任務在中斷的IPL處執行,并且在任務期間阻塞所有同等或更低優先級的中斷。
圖4.5顯示了一個內部資源(稱為InternalResource)的聲明,它在任務t1和任務t3之間共享。
圖4.5 使用rtaoscfg聲明內部資源
如果任務使用內部資源,RTA-OS將在調用任務的入口函數之前自動獲取內部資源。然后,在任務終止、調用Schedule()或WaitEvent()之后,資源將自動釋放。
在任務執行過程中,所有其他共享內部資源的任務將被阻止運行,直到內部資源釋放。
圖4.6顯示了共享相同內部資源的三個任務的執行情況。
圖4.6 內部資源的執行
重要的是要注意,當一個擁有內部資源的任務完成時,操作系統會根據就緒任務的正常(基本)優先級做出調度決策。如果一個任務正在運行,并且共享相同內部資源的多個任務已經激活,那么在運行的任務終止時,將選擇優先級最高的就緒任務來運行,然后按內部資源的最高優先級調度。
任何優先級低于內部資源優先級上限的任務(包括不共享內部資源的任務)在執行共享內部資源的任務時將被阻塞。可以在圖4.6中看到一個示例,其中優先級為1的Task1與優先級為3的Task共享內部資源。如果Task1在Task2或Task3啟動之前開始運行,那么這兩個任務將被延遲(阻塞),直到Task1完成。
然而,所有不共享內部資源的高優先級任務仍然可以搶占。圖4.7顯示,Task 1最初以優先級3運行,因為它與優先級3的任務共享一個內部資源。當Task 1運行時,Task 2就可以運行了。task2的優先級低于Task1的活動優先級,因此它不能搶占。當Task4被激活時,它可以搶占Task1,因為它的優先級是4,即它的優先級高于Task1的活動優先級。任務2只能在任務1終止時運行。
圖4.7 內部資源阻塞了不共享資源的任務
從這種行為可以清楚地看出,鎖定內部資源的任務將阻止任何優先級高于自身但優先級低于內部資源最高優先級的任務在整個任務期間運行。當低優先級任務阻止高優先級任務執行時,稱為阻塞。共享內部資源的任務相對于彼此非搶占性地運行。
一旦共享內部資源的集合中的任務獲得了對CPU的訪問權,它將在不被集合中的任何其他任務搶占的情況下運行。這樣做的結果是,與完全搶占式系統相比,高優先級任務可能需要更長的時間才能訪問CPU。
4.6 使用資源以最小化堆棧使用Using Resources to Minimize Stack Usage
資源在應用程序中的主要作用是在關鍵部分上提供互斥。然而,RTA-OS的單堆棧模型意味著資源有一個有用的次要角色——最小化堆棧使用。回想一下,共享資源的任務不會相互搶占。在RTA-OS使用的單堆棧模型中,這意味著它們的堆棧使用是有效覆蓋的。
可以利用這個特性來權衡系統中的時間和堆棧使用情況。下面幾節介紹對應用程序的簡單修改如何減少堆棧使用。所有這些修改都會在系統中引入額外的阻塞因素。
這些阻礙因素的影響取決于系統。回想一下,優先級上限協議確保任務或ISR在執行期間最多被阻塞一次。最壞阻塞時間是任何低優先級任務或ISR可以占用相同資源的最大時間。
這意味著,如果額外的阻塞因素小于或等于當前任務/ISR所遭受的最壞情況阻塞,則不會對響應時間產生影響,并且減少的堆棧使用將被釋放。如果額外的阻塞因素比當前的最壞情況阻塞更長,那么響應時間將更長。如果響應時間保持在任務/ ISR所需的截止日期之內,系統仍將正常運行。
4.6.1 內部資源Internal Resources
給定一組共享內部資源的任務,RTA操作系統使用的最壞情況堆棧等于使用最多堆棧的任務所需的最大堆棧空間。在傳統操作系統中,最大堆棧空間等于任務堆棧的總和,而不是它們的最大值。
如果需要最小化堆棧空間,那么可以通過在消耗大量堆棧的任務之間共享內部資源來利用RTA-OS的單一堆棧架構的優勢。圖4.8中的第一個堆棧顯示了5個搶占任務A、B、C、D和E的最壞情況堆棧消耗情況。通過在任務B和C之間以及任務D和E之間共享內部資源,可以顯著節省堆棧空間。圖4.8中的其他四個堆棧顯示了現在可能發生的情況——最壞的情況是A被B的最壞情況搶占,或者C被D和e的最壞情況搶占。從圖中可以看到,A被C搶占,被D搶占,這是最壞的情況,這比不使用內部資源時的堆棧要少得多。
圖4.8:使用內部資源節省堆棧空間
4.6.2 標準資源Standard Resources
如果一個任務調用一個使用大量堆棧的函數,那么可以考慮鎖定函數調用周圍的資源,并與優先級更高的任務共享資源。任務不需要在代碼中鎖定資源或調用函數——共享只是為了強制任務的執行以更高的優先級運行。這將防止高優先級任務在使用大量堆棧時搶占任務,從而減少總堆棧需求。
禁用函數調用周圍的中斷具有類似的效果——有效地用臨時屏蔽的ISR覆蓋函數調用的堆棧使用情況。
4.7 作為資源的調度程序The Scheduler as a Resource
如果一個任務有一個必須在不被系統中任何其他任務搶占的情況下執行的關鍵段(回想一下,調度程序是用來執行任務切換的),則該任務可以保留調度程序。為此目的,所有任務都可以使用一個名為RES_SCHEDULER的預定義資源。RES_SCHEDULER是任務共享數據的一種方便方法,無需手動聲明在所有任務之間共享的資源。
當一個任務獲得RES_SCHEDULER時,所有其他任務將被阻止搶占,直到該任務釋放RES_SCHEDULER。這實際上意味著任務在RES_SCHEDULER被占用的時間內是非搶占性的。
這比使整個任務非搶占性要好,特別是當任務只需要在其總執行時間的一小部分防止搶占時。
必須指定應用程序是否使用RES_SCHEDULER。這是在“一般”中設置的。如果配置RES_SCHEDULER,那么RTA-OS將自動生成一個稱為RES_SCHEDULER的標準資源,并在配置中的每個任務之間共享它。由于RES_SCHEDULER的行為類似于標準資源,可以創建鏈接到RES_SCHEDULER的鏈接資源,如圖4.9所示。
圖4.9:Linking to RES_SCHEDULER
使用RES_SCHEDULER可以改善低優先級任務的響應時間,否則這些任務可能會受到應用程序中其他任務的多次搶占,但代價是高優先級任務的響應時間更長。
如果您不需要在應用程序中使用RES_SCHEDULER,那么您可以通過禁用它的生成來節省ROM和RAM空間,如圖4.10所示。
圖4.10:Disabling RES_SCHEDULER
4.8 選擇一個搶占控制機制Choosing a Preemption Control Mechanism
如果在一對GetResource()和ReleaseResource()調用之間出現不需要鎖的代碼,則可能會降低系統的響應性。考慮到這一點,當您在應用程序中使用資源時,應該將GetResource()調用盡可能地放置在您使用該資源保護的代碼段附近。
然而,這條規則有一個例外。當有一個短時間運行的任務或ISR對同一資源進行多次GetResource()和ReleaseResource()調用時,就會出現此異常。API調用的成本可能會占整個任務執行時間的很大一部分,因此也可能占響應時間的很大一部分。
可能會發現,將整個任務或ISR主體放在GetResource()和ReleaseResource()調用之間實際上縮短了最壞情況下的響應時間。
應該盡可能避免使用非搶占式任務并獲取RES_SCHEDULER。當資源被占用的時間最少,并且影響的任務數量最少時,系統的響應性和可調度性就會得到改善。
4.9 避免競態條件Avoiding Race Conditions
調用TerminateTask()。在某些情況下,這可能會在應用程序中引入競態約束條件。這可能會導致錯過任務激活(您在本章開頭了解了競爭條件)。
例4.6展示了競態條件可能成為問題的系統類型。假設兩個BCC1任務在有界緩沖區上交換數據。
在例4.6中,在資源被釋放到任務結束之間,Read可以被Write搶占。當“寫”任務與“讀”任務連接時,激活將丟失。這是因為Read仍在運行。換句話說,一個任務正在被激活,但它沒有處于掛起狀態。
要解決這個問題,可以允許排隊激活Read任務。這意味著您應該將任務設置為BCC2。
#includeTASK(Write) /* Highest priority .*/ WriteBuffer(); GetResource(Guard); BufferNotEmpty = True; ReleaseResource(Guard); ChainTask(Read); } TASK(Read) /* Lowest priority. */ ReadBuffer(); GetResource(Guard); if( BufferNotEmpty ) { ReleaseResource(Guard); /* !!! Race condition occurs here !!! */ ChainTask(Read); } else { ReleaseResource(Guard); /* !!! Race condition occurs here !!! */ TerminateTask(); } }
Example 4.6: A System where a Race Condition can Occur
4.10 小結
?資源用于在訪問共享數據或硬件資源時提供互斥。
?任務和ISR可以共享任意數量的資源。
?所有GetResource()和ReleaseResource()調用必須正確嵌套。
?所有資源必須在任務或ISR終止前釋放。
?調度器可以作為資源使用,但如果可能的話,應該優先使用內部資源。
?內部資源為控制任務組和ISR之間的搶占提供了一種自由(Free)機制。
審核編輯:劉清
-
操作系統
+關注
關注
37文章
6742瀏覽量
123194 -
AUTOSAR
+關注
關注
10文章
350瀏覽量
21479 -
ISR
+關注
關注
0文章
38瀏覽量
14408 -
WIPL
+關注
關注
0文章
2瀏覽量
6188
原文標題:符合AUTOSAR標準的RTA-OS --Resources詳解
文章出處:【微信號:汽車電子嵌入式,微信公眾號:汽車電子嵌入式】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論