Steward
分享是一種喜悅、更是一種幸福
驅動程式 - Linux Device Driver (LDD) - 使用範例 - C/C++ (PocketBeagle) - Workqueue
在延遲中斷處理機制上,workqueue是另一個可以使用的方式,workqueue是執行在低優先級別上,因此,可以讓Context Switch繼續執行,意味著使用者可以在workqueue裡面呼叫sleep()相關的函式,這也是跟softirq、tasklet最大的差別,因此,workqueue是相當適合應用在耗時處理的場合
使用步驟:
1. alloc_workqueue() 2. INIT_WORK() 3. queue_work() 4. destroy_workqueue()
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #include <linux/init.h> #include <linux/device.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/mm.h> #include <linux/gpio.h> #include <linux/interrupt.h> MODULE_LICENSE ( "GPL" ); MODULE_AUTHOR ( "Steward Fu" ); MODULE_DESCRIPTION ( "Linux Driver" ); #define BUTTON 27 struct work_struct mywork = {0}; struct workqueue_struct *myworkqueue = NULL ; static void workqueue_handler ( struct work_struct *work) { printk ( "%s\n" , __func__ ); } static irqreturn_t irq_handler ( int irq, void *arg) { queue_work (myworkqueue, &mywork); return IRQ_HANDLED ; } int ldd_init ( void ) { myworkqueue = alloc_workqueue ( "myworkqueue" , 0, 0); INIT_WORK (&mywork, workqueue_handler ); request_irq ( gpio_to_irq ( BUTTON ), irq_handler , IRQF_TRIGGER_RISING , "gpio_irq" , NULL ); return 0; } void ldd_exit ( void ) { free_irq ( gpio_to_irq ( BUTTON ), NULL ); destroy_workqueue (myworkqueue); } module_init ( ldd_init ); module_exit ( ldd_exit ); |
ldd_init: 設定GPIO中斷以及workqueue延遲處理副程式
irq_handler: 安排一個workqueue延遲處理
workqueue_handler: 列印字串
ldd_exit: 釋放中斷資源以及刪除workqueue
完成
# workqueue_handler