Linux 2.6內核使用了不少工作隊列來處理任務,他在使用上和 tasklet最大的不同是工作隊列的函數可以使用休眠,而tasklet的函數是不允許使用休眠的。
工作隊列的使用又分兩種情況,一種是利用系統共享的工作隊列來增加自己的工作,這種情況處理函數不能消耗過多時間,這樣會影響共享隊列中其他任務的處理;別的一種是創建自己的工作隊列並添加工作。
(一)利用系統共享的工作隊列添加工作:
第一步:聲明或編寫一個工作處理函數
void my_func();
第二步:創建一個工作結構體變量,並將處理函數和參數的入口地址賦給這個工作結構體變量
DECLARE_WORK(my_work,my_func,&data); //編譯時創建名爲my_work的結構體變量並把函數入口地址和參數地址賦給它;
假如不想要在編譯時創建,就用DECLARE_WORK()創建並初始化工作結構體變量,也可以在程序運行時再用INIT_WORK()創建
struct work_struct my_work; //創建一個名爲my_work的結構體變量,創建後才能使用INIT_WORK()
INIT_WORK(&my_work,my_func,&data); //初始化已經創建的my_work,其實便是往這個結構體變量中添加處理函數的入口地址和data的地址,通常在驅動的open函數中完成
第三步:將工作結構體變量添加入系統的共享工作隊列
schedule_work(&my_work); //添加入隊列的工作完成後會自動從隊列中刪除
或
schedule_delayed_work(&my_work,tick); //延時tick個滴答後再提交工作
(二)創建自己的工作隊列來添加工作
第一步:聲明工作處理函數和一個指向工作隊列的指針
void my_func();
struct workqueue_struct *p_queue;
第二步:創建自己的工作隊列和工作結構體變量(通常在open函數中完成)
p_queue=create_workqueue("my_queue"); //創建一個名爲my_queue的工作隊列並把工作隊列的入口地址賦給聲明的指針
struct work_struct my_work;
INIT_WORK(&my_workmy_func,&data); //創建一個工作結構體變量並初始化,和第一種情況的辦法一樣
第三步:將工作添加入自己創建的工作隊列等待執行
queue_work(p_queue,my_work);
//作用與schedule_work()相似,不同的是將工作添加入p_queue指針指向的工作隊列而不是系統共享的工作隊列
第四步:刪除自己的工作隊列
destroy_workqueue(p_queue); //基本是在close函數中刪除