概述
在操作系統中,如果我們需要進行一項工作處理,往往需要創建一個任務來加入內核的調度隊列。一個任務對應一個處理函數,如果要進行不同的事務處理,則需要創建多個不同的任務。任務作為CPU調度的基本單元,任務數量越大,則調度成本越高。工作隊列(workqueue)機制簡化了基礎的任務創建和處理機制,一個workqueue對應一個實體task任務處理,workqueue下面可以掛接多個work實體,每一個work實體都能對應不同的處理接口。即用戶只需要創建一個workqueue,則可以完成多個掛接不同處理函數的工作隊列。其次,當某些實時性要求較高的任務中,需要進行較繁重鉤子處理時,可以將其處理函數掛在workqueue中,其執行過程將位于workqueue的上下文,而不會占用原有任務的處理資源。另外,workqueue還提供了work的延時處理機制,用戶可以選擇立即執行或是延時處理。當應用需要創建大量實時性要求不高的任務時,可以使用workqueue來統一調度;或者將任務中實時性要求不高的部分處理延后到workqueue中處理。如果需要設置延后處理,則需要使用work機制。注意:該機制不支持周期work的處理。
工作機制
workqueue的處理依賴于task任務。一個workqueue隊列會創建關聯其對應的task任務,一個workqueue會掛載多個work處理,每個work處理對應一個處理函數。當workqueue得到調度,即其關聯的task得到運行,在每次task的調度期間,都會從工作隊列中按照先后順序取出一個work來進行處理。workqueue模塊在初始化時,會創建一個系統默認的工作隊列,用戶可根據需要將work添加到該隊列中去執行。
工作隊列功能函數
函數名 | 描述 |
aos_workqueue_create() | 工作隊列創建函數 |
aos_workqueue_del() | 工作隊列刪除函數 |
aos_work_init() | work創建函數 |
aos_work_destroy() | work銷毀函數 |
aos_work_run() | work觸發函數 |
aos_work_sched() | work觸發函數(由系統默認工作隊列來執行) |
aos_work_cancel() | 工作隊列刪除函數 |
常用配置
消息隊列功能:默認使能,如需修改,在YAML中修改RHINO_CONFIG_BUF_QUEUE配置
def_config:
RHINO_CONFIG_WORKQUEUE: 0
API說明
使用示例
示例代碼參考example/workqueue_example.c, 該示例用工作隊列實現不同場景的任務執行。示例說明如下:
t0時刻,任務T調用aos_sem_create()創建一個信號量,調用aos_workqueue_create()創建一工作隊列wq1。 任務T然后調用aos_work_init()創建7個任務:work0、work1、work2、work3、work4、work5、work6,延遲參數分別為0、0、1、20、18、40、50。
t1時刻,任務T調用aos_work_run()依次: a、將work0加入工作隊列wq1 b、將work1加入工作隊列wq1 c、將work1再次工作隊列wq1 d、將work2加入工作隊列wq1 e、將work2加入工作隊列wq1 f、將work3加入工作隊列wq1 g、將work4加入系統默認工作隊列 h、將work5加入系統默認工作隊列 i、將work6加入系統默認工作隊列
t2時刻,任務T調用aos_sem_wait()等待信號量進入阻塞狀態,
t3時刻,work4被執行釋放信號量,任務T解除阻塞,將work5再加入系統默認工作隊列后因等待信號量進入阻塞狀態
t4時刻,work5被執行釋放信號量,任務T解除阻塞,釋放資源。
該示例可配置到helloworld_demo中運行,相關代碼的下載、編譯和固件燒錄均依賴AliOS Things配套的開發工具 ,所以首先需要參考《AliOS Things集成開發環境使用說明之搭建開發環境》,下載安裝 。 待開發環境搭建完成后,可以按照以下步驟進行示例的測試。
步驟1 創建或打開工程
打開已有工程
如果用于測試的案例工程已存在,可參考《AliOS Things集成開發環境使用說明之打開工程》打開已有工程。
創建新的工程
組件的示例代碼可以通過編譯鏈接到AliOS Things的任意案例(solution)來運行,這里選擇helloworld_demo案例。helloworld_demo案例相關的源代碼下載可參考《AliOS Things集成開發環境使用說明之創建工程》。
步驟2 添加組件
案例下載完成后,需要在helloworld_demo組件的package.yaml中添加對組件的依賴:
depends:
- osal_aos: dev_aos # helloworld_demo中引入osal_aos組件
步驟3 下載組件
在已安裝了的開發環境工具欄中,選擇Terminal -> New Terminal啟動終端,并且默認工作路徑為當前工程的workspace,此時在終端命令行中輸入:
aos install osal_aos
上述命令執行成功后,組件源碼則被下載到了./components/osal_aos路徑中。
步驟4 添加示例
osal_aos組件的package.yaml中添加example示例代碼:
depends:
- rhino: dev_aos
- cli: dev_aos # 添加cli依賴
source_file:
- "*.c"
- "example/workqueue_example.c" # 添加 workqueue_example.c
步驟5 編譯固件
在示例代碼已經添加至組件的配置文件,并且helloworld_demo已添加了對該組件的依賴后,就可以編譯helloworld_demo案例來生成固件了,具體編譯方法可參考《AliOS Things集成開發環境使用說明之編譯固件》。
步驟6 燒錄固件
helloworld_demo案例的固件生成后,可參考《AliOS Things集成開發環境使用說明之燒錄固件》來燒錄固件。
步驟7 打開串口
固件燒錄完成后,可以通過串口查看示例的運行結果,打開串口的具體方法可參考《AliOS Things集成開發環境使用說明之查看日志》。
當串口終端打開成功后,可在串口中輸入help來查看已添加的測試命令。
步驟8 測試示例
CLI命令行輸入:
workqueue_example
關鍵日志:
--WORK 0--
--WORK 1--
--WORK 1--
--WORK 2--
--WORK 4--
--WORK 3--
--WORK 6--
--WORK 5--
注意事項
當work延時參數為0時,調用aos_work_run()觸發多次,則會在對應工作隊列中會被執行多次;若work延遲參數不為0,調用aos_work_run()觸發多次,則只會在對應工作隊列中被執行一次。
FAQ
Q1: 系統默認工作隊列對應的任務優先級和棧大小是多少? 答:優先級為:20,棧大小為:3072字節。