?

基于STM32的mbedOS信號量調度機制剖析

2023-11-02 12:36劉中華王宜懷劉長勇王浩波
計算機應用與軟件 2023年10期
關鍵詞:信號量調用隊列

劉中華 王宜懷 劉長勇 王浩波

1(蘇州大學計算機科學與技術學院 江蘇 蘇州 215006)

2(武夷學院數學與計算機學院 福建 武夷山 354300)

0 引 言

隨著嵌入式實時操作系統(RTOS)[1-2]不斷發展,對于共享數據訪問的不一致現象屢見不鮮,而多任務[3]的并發調度是造成這一現象的主要原因。面對操作系統的同步問題,1968年荷蘭計算機科學家艾茲格·迪杰斯特拉提出了信號量(Semaphore)的概念[4-5],用來實現對操作系統的資源管理[6]和多任務調度。信號量機制在常用的RTOS中一直有被應用,無論是早期出現的MQX,還是之后陸續出現的諸如μC/OS、FreeRTOS及2014年Arm公司出品的mbedOS等RTOS中,信號量機制始終被保留并不斷完善[7]。因此,充分理解信號量的調度機制,有助于開發人員設計出實時性強、穩定性好的RTOS。目前,有關操作系統的信號量機制剖析主要集中在Linux、FreeRTOS、VxWorks等操作系統,并且不同的RTOS中信號量的名稱和實現細節不太一樣,例如FreeRTOS有二進制信號量、計數信號量、互斥量和遞歸互斥量,mbedOS只有互斥信號量和計數信號量;FreeRTOS中信號量的創建通過隊列實現,mbedOS通過構造結構體來創建信號量[8]。但對mbedOS中的信號量調度剖析方面缺乏資料。為此,本文對mbedOS中的信號量調度機制進行理論分析,重點剖析關鍵函數的實現原理并加以流程圖分析,利用STM32L431RC芯片結合SD-mbedOS工程框架[9]作為軟硬件環境,通過多個任務使用信號量機制的并行調度實驗,將實驗的整個調度流程以及當前所運行的時間通過printf函數[10]進行輸出顯示,最后對調度機制的理論執行時間和實際執行時間進行對比,從而分析mbedOS信號量調度機制的實時性。通過對信號量調度機制進行全面剖析并分析其實時性,有助于理解調度機制的執行流程,更加了解多任務的并發調度機制,同時也為分析其他RTOS的信號量調度機制提供了基礎[11]。

1 信號量的含義及其應用場合

在RTOS中,信號量通常被定義成一個提供信號的非負整型變量,來保證在多任務并發的環境下,能使得操作系統不會發生沖突,穩定運行。在操作系統的信號量機制的管理下,對共享資源的訪問同步問題都可以用信號量來實現。比如一個讀取數據任務和一個寫入數據任務要訪問共享資源緩沖區的問題,就能通過三個信號量來實現:SEM_Read,允許任務對緩沖區進行讀取操作;SEM_Write,允許任務對緩存區進行寫入操作;SEM_Mutex,限制緩沖區的互斥訪問。在同一時刻只能允許一個讀/寫任務訪問緩沖區,對緩沖區進行訪問之前必須先獲取信號量SEM_Mutex,并且任務執行完成后需釋放信號量[12]。在任何一個任務中,獲取信號量和釋放信號量是同時存在的,意味著在任務結束的時候,并不會占用信號量。在RTOS中,信號量的調度機制如圖1所示。

圖1 信號量調度的一般流程

正是信號量這種有序的特性,使得信號量能應用到很多場合:多任務之間的同步進行;對共享資源的訪問;為了實現更好的性能而控制任務的并發數等。

2 RTOS信號量調度機制及其關鍵要素

在RTOS中的同步與通信機制中,與設置事件字來表達多種可能的情況相比,信號量是一種簡單的同步手段。

2.1 RTOS信號量的調度機制

采用信號量作為任務與任務間或中斷與任務間的同步與通信的方法時,則必定有任務(或中斷)創建信號量,同時有任務等待獲取信號量[13]。信號量的獲取與釋放必須在同一任務中,例如在mbedOS中,任務調用Wait()函數獲取信號量,實際是通過判斷信號量控制塊結構體的Tokens變量來決定是否允許獲取信號量;在FreeRTOS中則是調用xSemaphoreTake()函數來獲取信號量,判斷隊列句柄xHandle中的uxMessageWaiting變量來決定是否允許獲取信號量。在任務執行操作完成后,會將信號量釋放,例如在mbedOS中通過調用Release()函數來釋放信號量;在FreeRTOS中調用xSemaphoreGive()函數來釋放信號量[14]。若當前等待隊列存在任務因等待獲取信號量而阻塞,則會將等待隊列中的優先級最高的任務移入就緒隊列等待調度。

2.2 信號量調度機制的關鍵要素

信號量作為RTOS中任務同步與通信的重要方法之一,其主要功能是實現任務之間的同步或多任務并發執行。在信號量調度機制過程中所涉及到的關鍵要素有信號量的創建、獲取、釋放、響應、調度等[15]。

(1) 信號量的創建:指明信號量的名稱,初始化信號量控制塊結構體并設置信號量數值的大小。

(2) 信號量的獲?。褐该髂膫€任務或中斷中請求獲取信號量,等待獲取信號量的時間為多少。

(3) 信號量的釋放:在任務獲取到信號量并執行完相關操作之后,釋放信號量,若信號量的等待隊列不為空,則取出任務準備進行調度。

(4) 信號量的響應:當信號量被獲取后,獲取信號量的任務會繼續往下執行,當操作完成后,會釋放信號量。

(5) 信號量的調度:當有任務釋放信號量時,會將等待隊列中優先級最高的任務與正在運行的任務的優先級進行比較,判斷是否需要重新進行任務調度。

3 mbedOS信號量調度機制理論剖析

mbedOS信號量機制首先從創建信號量開始,從程序開始運行到主任務執行app_init()函數后,會調用Semaphore()函數來創建信號量。任務可以分別調用Wait()函數和Release()函數來進行信號量的獲取和釋放[16]。

下面將著重分析信號量創建、信號量獲取和信號量釋放的過程以及函數調用。

3.1 信號量創建過程剖析

在mbedOS中使用信號量控制塊結構體來描述信號量,數據結構如下:

typedef struct{

uint8_t

id;//信號量ID

uint8_t reserved_state;

//互斥量狀態

uint8_t

flags;//信號量標志

uint8_t reserved;

const char

*name;//信號量名稱

osRtxThread_t *thread_list;

//信號量等待隊列

uint16_t

tokens;//當前信號量的數值

uint16_t max_tokens;

//信號量的最大數值

}osRtxSemaphore_t;

信號量創建函數調用順序為Semaphore()→Constructor()→osSemaphoreNew()→_svcSemaphoreNew()→SVC_Handler()→svcRtxSemaphoreNew()。信號量創建的流程如圖2所示。

圖2 信號量創建的流程

信號量的創建調用Semaphore()函數,傳入參數count表示創建信號量的數值大小。緊接著調用Constructor()函數,在該函數中初始化信號量屬性結構體osSemaphoreAttr_t和信號量控制塊結構體osRtxSemaphore_t。當初始化結構體后,調用osSemaphoreNew()函數來創建信號量。在任務模式下會調用_svcSemaphoreNew()函數,從而觸發SVC中斷,轉而去執行SVC_Handler中斷處理函數。然后實際執行的函數是svcRtxSemaphoreNew(),由該函數來執行信號量的創建。當信號量創建之后,會對信號量等待隊列thread_list是否為空進行判斷,若不為空,則說明存在任務等待獲取信號量,則從信號量等待隊列中取出優先級最高的任務放入就緒隊列,等待調度[17]。

3.2 信號量獲取過程剖析

信號量獲取函數調用順序為Wait()→OsSemaphoreAcquire()→_svcSemaphoreAcquire()→SVC_Handler()→svcRtxSemaphoreAcquire()。信號量獲取的流程如圖3所示。

圖3 信號量獲取的流程

信號量獲取通過調用Wait()函數,傳入參數millisec設置等待信號量的時間,在該函數中調用_wait()函數,然后再調用osSemaphoreAcquire()函數。由于處于任務模式下,則會調用_svcSemaphoreAcquire()函數,在該函數中會觸發SVC中斷,轉而去執行SVC_Handler中斷處理函數。而實際執行的是svcRtxSemaphoreAcquire()函數,在函數內部來判斷Tokens的數值是否大于0,若大于0,則表示任務可以獲取信號量,此時首先要屏蔽系統中斷,然后對信號量的數值進行減一操作,否則可能會多任務訪問信號量數據出現不一致;若不大于0,則會根據參數millisec進行阻塞當前任務或者返回獲取信號量失敗。

3.3 信號量釋放過程剖析

信號量釋放函數調用順序為Release()→OsSemaphoreRelease()→_svcSemaphoreRelease()→SVC_Handler()→svcRtxSemaphoreRelease()。信號量釋放的流程如圖4所示。

圖4 信號量釋放的流程

信號量的釋放和信號量獲取的過程大致相同。首先調用Release()函數,請求釋放信號量,然后會跳轉到osSemaphoreRelease()函數。當前處于任務模式下,則會調用_svcSemaphoreRelease()函數,從而觸發SVC中斷。而實際調用的是svcRtxSemaphoreRelease()函數,在該函數的執行過程中,對信號量阻塞隊列進行判斷,若為空,則直接調用SemaphoreTokenIncrement()函數進行釋放信號量;若不為空,則調用osRtxThreadListGet()函數喚醒隊列中優先級最高的任務,重新進行任務調度。

4 mbedOS信號量調度機制實踐分析

以ARM Cortex-M4為內核的STM32L431RC開發芯片結合意法半導體(ST)公司研發了STM32CubeIDE為開發環境對mbedOS中的信號量調度機制進行實踐。STM32L431RC芯片為64引腳LQFP封裝,Flash內存為256 KB(共有128個扇區),RAM內存為64 KB。在信號量調度機制的實踐中,使用了printf打樁輸出調試方法,對關鍵步驟進行文字輸出,可以更好地了解整個程序的運行。

4.1 功能設計

在SD-mbedOS工程框架下創建工程實例,實例的功能是:創建了三個優先級相同的任務Td1、Td2和Td3,數值為2的信號量SP,按照Td1、Td2和Td3的順序啟動三個任務。在Td1任務中,先請求獲取信號量,獲取成功后Td1任務延時5 s;在Td2任務中,獲取信號量成功后,延時2 s。在Td3任務中,獲取信號量后,延時5 s,然后切換STM32L431RC芯片上的綠燈的亮暗。在信號量獲取和釋放的前后,輸出當前系統的運行時間,以便算出實際執行時間。三個任務(Td1、Td2和Td3)的內存地址分別為0x200016BC、0x2000177C和0x2000183C。實例的功能流程如圖5所示。

圖5 實例工程的功能流程

4.2 調度過程剖析

結合實例對mbedOS中信號量機制的調度過程進行更細致的分析,將當前運行的任務、任務的狀態、系統所執行的時間用printf函數的方式進行輸出。

(1) 任務啟動。芯片上電啟動最后轉到主任務函數中執行,先后啟動三個任務,然后阻塞該函數的運行,由mbedOS負責對任務的調度運行。printf輸出結果如下(下同):

Td1、Td2和Td3任務啟動完成,同時阻塞主任務。

(2) Td1任務請求獲取信號量。在主任務阻塞后,mbedOS從就緒隊列中取出優先級最高的任務(此時為Td1)開始執行。任務啟動后請求獲取信號量,初始信號量數值為2,Td1任務獲取信號量成功,信號量數值減2變為1。

Td1任務(200016BC)請求獲取SP,當前時間:3.441 44 s。

SP=2!=0,表示當前任務(200016BC)可獲取SP。

Td1任務獲取SP成功,當前時間:3.445 627 s,延時5 s。

(3) Td2任務請求獲取信號量。當前信號量SP的數值為1,Td2任務可以獲取信號量SP。

Td2任務(2000177C)請求獲取SP,當前時間:3.447 029 s。

SP=1!=0,表示當前任務(2000177C)可獲取SP。

Td2任務獲取SP成功,當前時間:3.461 119 s,延時2 s。

(4) Td3任務請求獲取信號量。由于當前SP的數值為0,Td3任務請求獲取信號量失敗,會將Td3任務添加到信號量阻塞隊列和延時等待隊列中。

Td3任務(2000183C)請求獲取SP,當前時間:3.452 028 s。

SP=0,表示當前任務(2000183C)獲取SP失敗。

將當前任務(2000183C)放入等待隊列和SP阻塞隊列,獲取就緒隊列中的任務,當前時間:3.466 121 s。

(5) Td2任務釋放信號量。當信號量SP被Td1和Td2獲取之后,在Td2任務延時2 s后會釋放信號量,由于在信號量阻塞隊列中有一個Td3任務等待獲取信號量,因此,在Td2任務釋放信號量之后,會將Td3任務從延時等待隊列和信號量阻塞隊列中取出,并放入就緒隊列中準備運行。此時Td3任務已經獲取到信號量,可以看成是Td2任務將信號量轉移給Td3任務,當前信號量數值還是為0。

Td2任務釋放SP,當前時間:8.053 098 s。

從等待隊列和SP阻塞隊列中獲取等待SP的任務(2000183C),當前時間:8.055 977 s。

Td2任務釋放SP成功,當前時間:8.056 314 s。

Td3任務獲取SP成功,當前時間:8.062 021 s,延時5 s并切換綠燈亮暗。

(6) Td2任務開始新一輪的請求獲取信號量。Td2任務釋放信號量后,重新開始獲取信號量SP,此時信號量被Td1任務和Td3任務占據,信號量數值為0。因此,Td2任務放入信號量阻塞隊列和延時等待隊列中,同時從就緒隊列中取出Td1任務準備運行。

Td2任務(2000177C)請求獲取SP,當前時間:11.505 674 s。

SP=0,表示當前任務(2000177C)獲取SP失敗。

將當前任務(2000177C)放入等待隊列和SP阻塞隊列,獲取就緒隊列中的任務,當前時間:11.519 806 s。

(7) Td1任務釋放信號量。Td1任務延時5 s結束,釋放信號量。此時信號量阻塞隊列中有Td2任務在等待獲取信號量,當Td1任務釋放信號量之后,將Td2任務從延時等待隊列和信號量阻塞隊列中取出,并放入就緒隊列中準備運行。

Td1任務釋放SP,當前時間:16.074 655 s。

從等待隊列和SP阻塞隊列中獲取等待SP的任務(2000177C),當前時間:16.082 538 s。

Td1任務釋放SP成功,當前時間:16.083 962 s。

Td2任務獲取SP成功,當前時間:16.090 021 s,延時2 s。

(8) Td1任務開始新一輪的請求獲取信號量SP。Td1任務請求獲取信號量SP,當前SP數值為0,將Td1任務放入延時等待隊列和信號量阻塞隊列中。

Td1任務(200016BC)請求獲取SP,當前時間:19.533 285 s。

SP=0,表示當前任務(200016BC)獲取SP失敗。

將當前任務(200016BC)放入等待隊列和SP阻塞隊列,獲取就緒隊列中的任務,當前時間:19.547 460 s。

(9) Td2和Td3任務釋放信號量。Td2任務延時結束后,釋放信號量。同時將Td1任務從延時等待隊列和信號量阻塞隊列中移出,并放入就緒隊列中運行。在Td2任務釋放信號量后,Td3任務延時結束釋放信號量(幾乎可以看作同時),此時信號量數值為1,故Td2獲取信號量成功,開始運行。

Td2任務釋放SP,當前時間:21.834 034 s。

從等待隊列和SP阻塞隊列中獲取等待SP的任務(200016BC),當前時間:21.836 s。

Td2任務釋放SP成功,當前時間:21.837 424 s。

Td3任務釋放SP,當前時間:21.838 129 s。

Td3任務釋放SP成功,當前時間:21.841 097 s。

Td1任務獲取SP成功,當前時間:21.843 022 s,延時5 s。

(10) Td1、Td2和Td3任務新一輪的請求獲取信號量。此時開始的運行情況和之前一樣,循環之前的過程。按照Td1、Td2和Td3的順序反復獲取信號量執行。任務的調度時序圖如圖6所示。

圖6 基于信號量機制的任務調度時序圖

4.3 調度性能剖析

任務信號量的獲取和釋放的理論時間是判斷mbedOS中信號量機制的實時性好與壞的性能標準。在SD-mbedOS架構下,系統時鐘頻率為48 MHz,一個指令周期的時間為0.020 8 μs。以任務請求獲取信號量為例,進行理論時間和實際執行時間的比較,在信號量數值不為0的情況下,任務申請獲取信號量的機器指令有461條,機器指令的條數是以執行一條_NOP指令所花費的時間為基準,所有執行的機器指令都能在編譯之后生成的.lst文件中找到,關鍵函數及其對應的機器碼和匯編指令如表1所示。

表1 關鍵函數及其對應的機器碼和匯編指令

根據計算得:信號量獲取的理論時間為10.44 μs,而在單個任務執行的情況下,信號量獲取(信號量數值不為0)的實際執行時間為14.8 μs,理論時間和實際時間的誤差在微秒級別,誤差在可接受的范圍內。

在工程實例中,將任務請求獲取信號量前后、釋放信號量前后的系統運行時間輸出。三個任務具體的調度時間如表2所示。

表2 信號量獲取和釋放的實際執行時間 單位:ms

表2中獲取信號量I和獲取信號量II分別表示:獲取信號量時信號量數值不為0和為0,獲取信號量II中的時間I表示信號量數值為0,將任務添加到相應隊列的時間,時間II表示在任務添加到隊列中后,到獲取信號量成功的時間。釋放信號量I和釋放信號量II分別表示:釋放信號量時信號量阻塞隊列為空和不為空,而時間III表示從隊列中移出任務的時間,時間IV表示其他時間。

表2中的時間是結合實例工程中三個任務的延遲時間計算的,由于實例中是多任務并發,并且系統的運行狀態用printf方法進行輸出,故信號量調度機制中的操作耗時較多??偟膩砜?信號量的獲取和釋放需要的時間很短,具有很好的實時性。

5 結 語

mbedOS的信號量調度機制是一個較為復雜的過程,其中涉及到多任務并發調度、任務對信號量的獲取和釋放、就緒隊列和等待隊列等的管理,其中的函數調用關系也較為復雜,觸發到的中斷函數有SVC中斷和Systick中斷等。本文重點剖析mbedOS中的信號量調度機制及其關鍵函數,加以流程圖總結,通過多任務并發的調度實驗,將調度過程中任務的切換、狀態的變化、當前系統運行時間進行輸出,給出時序圖分析,進一步驗證信號量調度機制理論分析的正確性,最后還對調度過程進行實時性能剖析,結果表明信號量調度機制的實時性能較好。通過對信號量調度機制的剖析,有助于更好地理解mbedOS的多任務并發機制,也為其他RTOS的信號量機制分析提供了基礎。

猜你喜歡
信號量調用隊列
隊列里的小秘密
基于多隊列切換的SDN擁塞控制*
核電項目物項調用管理的應用研究
在隊列里
LabWindows/CVI下基于ActiveX技術的Excel調用
Nucleus PLUS操作系統信號量機制的研究與測試
豐田加速駛入自動駕駛隊列
基于系統調用的惡意軟件檢測技術研究
硬件信號量在多核處理器核間通信中的應用
μC/OS- -III對信號量的改進
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合