中斷下半部分機制--tasklet和工作隊列
1.tasklet
tasklet機制是內核定義的幾種softirq之一(常用)
根據優先級不同內核將tasklet分成兩種:TASKLET_SOFTIRQ 和 HI_SOFTIRQ (後者優先級高)
執行時機通常是上半部分返回的時候。
1.1 tasklet機制初始化
在linux系統內核初始化的時候,通過調用softirq_init( )爲TASKLET_SOFTIRQ 和 HI_SOFTIRQ
安裝了執行函數。
1.2 相關的操作
struct tasklet_struct
{
struct tasklet_struct *next; //用來將系統中tasklet鏈接成鏈表
unsigned long state; //記錄在系統中tasklet的狀態
atomic_t count; //如果爲0,則不可被調度執行
void (*func)(unsigned long); //在tasklet上執行函數或者延遲函數
unsigned long data; //將data傳遞給fun指向的函數
};
1.2.1 初始化tasklet
聲明並初始化一個靜態的tasklet對象;
//struct tasklet_struct name;
//void func(unsigned long);
//unsingned long data;
DECLARE_TASKLET(name, func, data);
動態初始化tasklet對象
void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data)
-->tasklet_init(&name, fun, data);
1.2.2 提交一個tasklet
在聲明和初始化一個tasklet對象之後,
驅動程序需要調用tasklet_schedule來向系統提交tasklet(一般在中斷處理程序中提交)
void tasklet_schedule(struct tasklet_struct *t)
tasklet_schedule(name);
驅動模型:
2. 工作隊列
2.1 使用內核自己帶的工作隊列
工作隊列和tasklet相似,工作隊列執行的上下文是內核線程,因此可以調度和睡眠
在Workqueue機制中,Linux系統在初始化的時候通過init_workqueues(void)函數創建了一個workqueue隊列——events,
用戶可以直接初始化一個work_struct對象,然後在該隊列中進行調度,使用更加方便。
struct work_sturct my_wrok;//定義一個工作節點
void my_wq_func(struct work_struct *work);//定一個處理函數
INIT_WORK(&my_work, my_wq_func) /*初始化工作節點,並和處理函數綁定*/
schedule_work(&my_wq) /*使用內核自己創建的工作隊列-events和處理線程, 提交工作節點(一般在中斷處理函數中)*/
---> queue_work(system_wq, work);
2.2 使用自己創建工作隊列
首先創建工作隊列:
#define create_workqueue(name)
alloc_workqueue((name), WQ_MEM_RECLAIM, 1)
--->struct workqueue_struct* myworkqueue = create_workqueue("mywq"); /*創建工作隊列和處理線程*/
提交工作:
int queue_work(struct workqueue_struct *wq, struct work_struct *work)
-->queue_work(myworkqueue, &my_work);