在學習之前可以先去了解壹下工作隊列的使用場景: 工作隊列 ( workqueue ) 。
簡而言之,工作隊列就是將壹些工作任務的執行延遲,交由內核線程異步執行。
最簡單的使用方式就是開啟 RT-Thread 的系統工作線程(System workqueue),而我們往系統工作線程裏提交工作項(work item)即可。
RT-Thread 其實給我們提供了壹個系統工作線程了,但很少有人知道。配置選項路徑如下圖所示:
依次選中上述這些選項,就能夠開啟系統工作隊列了。而且還可以看到工作隊列線程的棧大小默認為 2048,優先級為 23 。
這樣系統在初始化的時候就創建了系統工作隊列了,名字叫作 sys_work ,在終端輸入 ps 能夠看到該線程。
如何向系統工作線程裏添加工作項呢?
rt_work_submit() 用於向系統工作隊列添加工作項, rt_work_cancel() 用於從系統工作隊列中取消某壹個工作項。
當然,在提交工作項時,需要初始化該工作項,綁定相應的回調函數和用戶指針,接口如下:
這樣,我們就可以隨時隨地地提交工作任務執行了,極大地方便了程序的組織。
用壹個小例程測試壹下:
在 qemu 項目裏的 main.c 裏輸入:
然後執行就能看到下述效果,與工作項綁定的任務被異步執行了,而且工作項 1 延遲了 2 個 tick 才執行。
rt_workqueue 的接口有很多,我們只需要關註常用的即可。
首先使用 rt_workqueue_create() 創建壹個工作隊列,然後使用 rt_workqueue_submit_work() 提交工作項,使用 rt_workqueue_cancel_work() 取消工作項,當然還可以使用 rt_workqueue_destroy() 銷毀壹個工作隊列。其他的接口有興趣的可以了解,但常用的就是上面這四種。
這裏提交任務與上述使用系統工作隊列的唯壹不同之處就是我們需要手動指定工作隊列,其他的都是壹模壹樣的。
用壹個小例程測試壹下:
在 qemu 項目裏的 main.c 裏輸入:
然後執行就能看到下述效果,與工作項綁定的任務被異步執行了,而且工作項 1 延遲了 2 個 tick 才執行。
關於實現部分我這裏不介紹具體細節,做了壹些動畫給大家展示壹下內部過程
工作隊列裏面有壹個線程(workthread),這個線程的任務就是不斷地從掛載鏈表(worklist)裏提取工作項執行,若沒有則休眠。
然後提交工作項時,若延遲時間 time 大於 0,則啟動該工作項的定時器,定時結束後再加入掛載鏈表(worklist)。
若提交工作項時延遲實際等於 0,則直接將該工作項掛加入到掛載鏈表(worklist)。
當然,工作項的定時器超時後,會自動將該工作項加入到掛載鏈表(worklist)。