FreeRTOS在MCU領域應用非常廣泛,今天就給大家講解一下FreeRTOS調度器中的三種調度算法,以及在瑞薩RZ/T2L MPU中的應用。
1.任務狀態和事件的概述
RTOS,即實時操作系統,是一種能夠在規定時間內響應外部事件或數據,并控制生產過程或對處理系統做出快速響應的操作系統。RTOS通過調度一切可利用的資源完成實時任務,并控制所有實時任務協調一致運行。RTOS的主要特點包括提供及時響應和高可靠性。
在RTOS中,任務狀態通常包括以下幾種:
就緒態(Ready):任務已經準備好執行,所有必要資源都已經準備就緒,只等待RTOS調度器選中并分配CPU時間。新創建的任務通常立即進入就緒狀態,等待調度器的調度。
運行態(Running):任務正在執行,占據了CPU資源。當任務被RTOS調度器選中后,其上下文會被加載到CPU寄存器中,開始執行任務代碼。
阻塞態(Blocked):任務暫時不能執行,通常是因為等待某些外部事件,如I/O操作完成、定時器到期、信號量或互斥量被釋放等。一旦這些事件發生,任務會重新進入就緒狀態,等待調度器的調度。
掛起態(Suspended):任務被主動掛起,不參與調度,需要手動恢復才能回到就緒態。掛起狀態的任務不會執行,直到被其他任務或中斷調用特定的API函數恢復。
RTOS中的事件是指能夠觸發任務狀態改變或任務執行的某些外部或內部發生的情況。事件可以是來自硬件的中斷、定時器到期、消息隊列中的消息到達等。RTOS通過事件來同步和協調任務的執行,確保它們能夠按照預期的方式和時間順序運行。
2.FreeRTOS調度算法
FreeRTOS它支持多種任務調度算法,可通過配置來滿足不同應用的需求。
通過配置 configUSE_PREEMPTION 和 configUSE_TIME_SLICING 來更改算法。這兩個常量都在FreeRTOSConfig.h中定義。
還有個配置常數configUSE_TICKLESS_IDLE也會影響調度算法,因為使用它會導致tick中斷在很長一段時間內被完全關閉。
configUSE_TICKLESS_IDLE是一個高級選項,專門用于必須最小化功耗的應用程序。configUSE_TICKLESS_IDLE在之后解說。
對于相同優先級的任務,FreeRTOS調度器依次選中相同優先級的任務進入運行態。這種輪流策略被稱為‘Round Robin Scheduling’
‘Round Robin Scheduling’算法并不能保證同等優先級的任務之間運行相同的時間,只能保證同等優先級的“就緒”任務會依次進入“運行”態。
2.1
基于時間片的搶占式調度
如果按照如下配置:
configUSE_PREEMPTION 1
configUSE_TIME_SLICING 1
FreeRTOS調度器使用一種稱為“基于時間片的固定優先級搶占式調度”的調度算法,這是大多數小型RTOS應用程序使用的調度算法。
固定優先級
被描述為“固定優先級”的調度算法不會改變分配給被調度任務的優先級,但也不會阻止任務本身改變自己的優先級或其他任務的優先級。
搶占式調度
在優先級高于運行態任務的任務進入就緒態時,調度器立即讓這個高優先級的任務“搶占”運行態任務。被搶占意味著任務移出運行態并進入就緒態,并不是因為任務自己主動讓出或者阻塞。
時間片
時間片用于在具有相同優先級的任務之間共享處理時間,即使任務沒有顯式地讓步或進入阻塞狀態。使用“時間片”的調度算法將在每個時間片結束時選擇一個新任務進入運行狀態,如果有其他與運行任務具有相同優先級的就緒狀態任務。一個時間片等于兩個RTOS tick中斷之間的時間。
上圖演示了使用“基于時間片的固定優先級搶占式調度”算法搶占調度任務的調度過程。
task1是最高優先級的事件驅動任務,task2是中等優先級的周期性任務,task3是最低優先級的事件驅動任務,Idle task是空閑任務。
task1周期性運行,阻塞時,空閑任務就會運行,task3的事件到達就會搶占空閑任務,task3運行期間,如果task2的周期到了,因為task2優先級高就會搶占task3,task2運行完了再接著運行task2,task2運行期間,由于task1優先級高,一旦task1等待的事件到了就會搶占task2。
有相同優先級任務的情況:
task1是優先級最高的事件驅動任務,task2是和Idle task優先級相同的持續處理型任務。
task2和空閑任務就會輪流運行,而task1則可以搶占task2和空閑任務。
假如空閑任務里其實沒做什么事情,我們想讓和空閑任務相同優先級的Task2有更多的運行時間就可以配置configIDLE_SHOULD_YIELD。
如果configIDLE_SHOULD_YIELD設置為0,那么空閑任務將在整個時間片中保持運行狀態,除非它被更高優先級的任務搶占。
如果configIDLE_SHOULD_YIELD設置為1,如果有其他空閑優先級任務處于就緒狀態,那么空閑任務將主動讓出運行時間。
2.2
不帶時間片的搶占式調度
配置如下時,調度算法就會變成不帶時間片的搶占式調度
configUSE_PREEMPTION 1
configUSE_TIME_SLICING 0
和前面的唯一區別就是相同優先級的任務之間不會隨時間自動切換。
如果不使用時間片,那么調度程序只會在發生這兩種情況時,進行任務切換:
1
優先級更高的任務進入“就緒”態。
2
運行態任務變為阻塞態或被掛起。
很顯然,不使用時間片時,任務切換的情況會變少,所以關閉時間切片可以減少調度器的處理開銷。但是關閉時間切片也可能導致具有相同優先級的任務獲得的處理時間相差很大。因此,一定要慎重使用。
task1為最高優先級的事件驅動任務,task2和Idle task有相同的優先級。但是由于關閉了時間片,任務切換只會在空閑任務阻塞或者掛起或者task1搶占后發生,所以空閑任務和task2雖然優先級相同,但是明顯空閑任務占有的時間長很多。
2.3
協同調度
configUSE_PREEMPTION 0
configUSE_TIME_SLICINGx
當使用協同調度時,只有當運行態任務進入阻塞態,或者運行態任務通過調用taskYIELD()主動讓出,才會發生任務切換。
任務永遠不會被搶占,不能使用時間片,時間片配置的值隨便,無所謂。
task1、2、3優先級依次變低,剛開始task3運行,雖然task1和2優先級高,并且沒有阻塞,但是也無法搶占,task3調用taskYIELD(),主動讓出,因為task1優先級比task2高,task1就運行了,task1運行夠了進入阻塞態,由于task2比task3優先級高,task2就運行了。
在RZ/T2L上做的實驗
如果兩個參數設置為:configUSE_PREEMPTION =0,configUSE_TIME_SLICING= 0或者1(隨便) 稱之為協同調度,當使用協同調度時,只有當運行態任務進入阻塞態,或者運行態任務通過調用taskYIELD()主動讓出,才會發生任務切換。
任務永遠不會被搶占,不能使用時間片,時間片配置的值隨便。我做了一個實驗截圖如下:
上面的實驗說明“只有當運行態任務進入阻塞態,或者運行態任務通過調用taskYIELD()主動讓出,才會發生任務切換”,此時與時間片1 ms已經沒有什么關系了。
如果兩個參數設置為 configUSE_PREEMPTION =1,configUSE_TIME_SLICING=1, 此時只有兩個任務并且優先級相同,每個任務都持續做一件事情就會出現時間征為1ms的輪轉情況:
通過上面的兩個實驗可以說明,時間片存的意義是相同優先級并且持續時間較長的處理任務,需要平等分享CPU使用權。但是如果一旦有一方主動放棄CPU或者阻塞或者更高優先級任務來了,調度器是不會等待一個時間片完全結束,再去調度就緒列表中的任務的,而是直接調用就緒列表里的第一個任務。這樣的設計我認為是合理的,如果一定要等待時間片結束,是存在嚴重的資源浪費的。
審核編輯:劉清
-
寄存器
+關注
關注
31文章
5343瀏覽量
120348 -
定時器
+關注
關注
23文章
3248瀏覽量
114792 -
中斷處理
+關注
關注
0文章
94瀏覽量
10976 -
FreeRTOS
+關注
關注
12文章
484瀏覽量
62172 -
調度算法
+關注
關注
1文章
68瀏覽量
11980 -
調度器
+關注
關注
0文章
98瀏覽量
5247
原文標題:熱文分享| FreeRTOS任務調度器的三種調度算法和應用
文章出處:【微信號:麥克泰技術,微信公眾號:麥克泰技術】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論