Linux內(nèi)核中斷處理“下半部”機制(下)(超詳細~)
繼上篇文Linux內(nèi)核中斷處理“下半部”機制(上)(超詳細~)
4. 中斷處理的工作隊列機制
工作隊列(work queue)是另外一種將工作推后執(zhí)行的形式,它和前面討論的tasklet有所不同。工作隊列可以把工作推后,交由一個內(nèi)核線程去執(zhí)行,也就是說,這個下半部分可以在進程上下文中執(zhí)行。這樣,通過工作隊列執(zhí)行的代碼能占盡進程上下文的所有優(yōu)勢。最重要的就是工作隊列允許被重新調(diào)度甚至是睡眠。
那么,什么情況下使用工作隊列,什么情況下使用tasklet。如果推后執(zhí)行的任務需要睡眠,那么就選擇工作隊列;如果推后執(zhí)行的任務不需要睡眠,那么就選擇tasklet。另外,如果需要用一個可以重新調(diào)度的實體來執(zhí)行你的下半部處理,也應該使用工作隊列。它是唯一能在進程上下文運行的下半部實現(xiàn)的機制,也只有它才可以睡眠。這意味著在需要獲得大量的內(nèi)存時、在需要獲取信號量時,在需要執(zhí)行阻塞式的I/O操作時,它都會非常有用。如果不需要用一個內(nèi)核線程來推后執(zhí)行工作,那么就考慮使用tasklet。
4.1 工作、工作隊列
如前所述,我們把推后執(zhí)行的任務叫做工作(work),描述它的數(shù)據(jù)結構為work_struct,這些工作以隊列結構組織成工作隊列(workqueue),其數(shù)據(jù)結構為workqueue_struct,而工作線程就是負責執(zhí)行工作隊列中的工作。系統(tǒng)默認的工作者線程為events,自己也可以創(chuàng)建自己的工作者線程。表示工作的數(shù)據(jù)結構用<linux/workqueue.h>中定義的work_struct結構表示:
這些結構被連接成鏈表。當一個工作者線程被喚醒時,它會執(zhí)行它的鏈表上的所有工作。工作被執(zhí)行完畢,它就將相應的work_struct對象從鏈表上移去。當鏈表上不再有對象的時候,它就會繼續(xù)休眠。
表示工作隊列的數(shù)據(jù)結構用<kernel/workqueue.c>中定義的workqueue_struct:
4.2 創(chuàng)建推后的工作
4.2.1 靜態(tài)地創(chuàng)建工作(work_struct)
要使用工作隊列,首先要做的是創(chuàng)建一些需要推后完成的工作??梢酝ㄟ^DECLARE_WORK在編譯時靜態(tài)地建該結構:
? ? DECLARE_WORK(name, func);
其定義如下:
舉例如下:
即創(chuàng)建了一個全局靜態(tài)變量:static work_struct poweroff_work,且被初始化了,其執(zhí)行函數(shù)為do_poweroff。
【文章福利】小編推薦自己的Linux內(nèi)核技術交流群:【891587639】整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)? ? ? ? ?


4.2.2 動態(tài)初始化工作(work_struct)
先定義一具struct work_struct 變量,在需要使用時調(diào)用INIT_WORK進行初始化,然后便可以使用。
舉例如下:
4.3 對工作進行調(diào)度
現(xiàn)在工作已經(jīng)被創(chuàng)建,我們可以調(diào)度它了。想要把給定工作的待處理函數(shù)提交給缺省的events工作線程,只需調(diào)用: ? ? ?int schedule_work(struct work_struct *work); ?
它把work放入全局工作隊列:system_wq,其定義如下:
queue_work:把一個工作放入工作隊列:
把work放入工作隊列,work馬上就會被調(diào)度,一旦其所在的處理器上的工作者線程被喚醒,它就會被執(zhí)行。有時候并不希望工作馬上就被執(zhí)行,而是希望它經(jīng)過一段延遲以后再執(zhí)行。在這種情況下,可以調(diào)度它在指定的時間執(zhí)行:
4.4 創(chuàng)建工作者線程
工作放入工作隊列之后,由管理此工作隊列的工作者來執(zhí)行這些work,通過alloc_workqueue或create_singlethread_workqueue來創(chuàng)建工作者線程,它最后調(diào)用kthread_create創(chuàng)建線程,其線程名為alloc_workqueue中指定的name,其舉例如下:
