1. 程式人生 > >中斷底半部機制之tasklet詳解

中斷底半部機制之tasklet詳解

tasklet 的使用較簡單,我們只需要定義tasklet 及其處理函式並將兩者關聯,例如:

void my_tasklet_func(unsigned long); /*定義一個處理函式*/
DECLARE_TASKLET(my_tasklet, my_tasklet_func, data);
/*定義一個tasklet 結構my_tasklet,與my_tasklet_func(data)函式相關聯*/

程式碼 DECLARE_TASKLETmy_tasklet,my_tasklet_func,data)實現了定義名稱為my_tasklet tasklet並將其與my_tasklet_func()

這個函式繫結,而傳入這個函式的引數為data。my_tasklet的型別為struct tasklet_struct。

在需要排程 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