中斷底半部機制之tasklet詳解
阿新 • • 發佈:2018-11-25
tasklet 的使用較簡單,我們只需要定義tasklet 及其處理函式並將兩者關聯,例如:
void my_tasklet_func(unsigned long); /*定義一個處理函式*/
DECLARE_TASKLET(my_tasklet, my_tasklet_func, data);
/*定義一個tasklet 結構my_tasklet,與my_tasklet_func(data)函式相關聯*/
程式碼 DECLARE_TASKLET(my_tasklet,my_tasklet_func,data)實現了定義名稱為my_tasklet 的tasklet並將其與my_tasklet_func()
在需要排程 tasklet 的時候引用一個tasklet_schedule()函式就能使系統在適當的時候進行排程執行,如下所示:
tasklet_schedule(&my_tasklet);
使用 tasklet 作為底半部處理中斷的裝置驅動程式模板如下所示(僅包含與中斷相關的部分)。
/*定義tasklet 和底半部函式並關聯*/ void xxx_do_tasklet(unsigned long); DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0); /*中斷處理底半部*/ void xxx_do_tasklet(unsigned long) { ... } /*中斷處理頂半部*/ irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs) { ... tasklet_schedule(&xxx_tasklet);/*在合適的時機呼叫底半部*/ ... } /*裝置驅動模組載入函式*/ int __init xxx_init(void) { ... /*申請中斷*/ result = request_irq(xxx_irq, xxx_interrupt, SA_INTERRUPT, "xxx", NULL); ... } /*裝置驅動模組解除安裝函式*/ void __exit xxx_exit(void) { ... /*釋放中斷*/ free_irq(xxx_irq, xxx_interrupt); ... }
上述程式在模組載入函式中申請中斷(第24 行),並在模組解除安裝函式中釋放它(第33 行)。
對應於xxx_irq 的中斷處理程式被設定為xxx_interrupt()函式,在這個函式中,第15 行的tasklet_schedule(&xxx_tasklet)排程的tasklet 函式xxx_do_tasklet()在適當的時候得到執行。上述程式碼第 12 行顯示中斷處理程式頂半部的返回型別為irqreturn_t,它定義為int,中斷處理程式頂半部一般返回IRQ_HANDLED。