Tasklet和timer類似(基本上都是運作在Softirqs上面),但是不同於timer會在特定時間執行,tasklet會在下一次interrupt來臨時執行。Tasklet有兩種implement,分別為TASKLET_SOFTIRQ和HI_SOFTIRQ,這兩種的差別在於HI_SOFTIRQ筆TASKLET_SOFTIRQ早執行。另外Tasklet只在註冊的CPU上面執行,而且註冊的tasklet同一時間只會被某個CPU執行。
您可以dynamically或statically的建立tasklet,
DECLARE_TASKLET(task, func, data);
DECLARE_TASKLET_DISABLED(task, func, data);
tasklet_init(task, func, data);
宣告後,還必須呼叫tasklet_schedule(task)才會被執行,但如果是用
DECLARE_TASKLET_DISABLED()宣告成disabled狀態,那就還必須用tasklet_enable()將其狀態設成enabled才能被執行。您也可以透過tasklet_disabled() disabled某個tasklet。tasklet_kill()可以保證tasklet不會被schedule,如果已經在執行,就會等它執行結束。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
static void f(unsigned long name);
// create tasklet statically
static DECLARE_TASKLET(t1, f, (unsigned long)"t1");
static DECLARE_TASKLET_DISABLED(t2, f, (unsigned long)"t2");
static struct tasklet_struct *t3;
static void f(unsigned long name)
{
printk("%s(): on cpu %d\n", (char*)name, smp_processor_id());
}
static void f3(unsigned long name)
{
static u32 c = 0;
tasklet_schedule(t3);
if (!(c++ % 2000000)) { // 每隔2000000次呼叫就印出訊息
printk("%s(): on cpu %d\n", (char*)name, smp_processor_id());
}
}
static int __init init_modules(void)
{
// create tasklet dynamically
t3 = kzalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
tasklet_init(t3, f3, (unsigned long)"t3");
tasklet_schedule(&t1);
tasklet_schedule(&t2);
tasklet_schedule(t3);
tasklet_enable(&t2); // 沒有enable就不會被啟動
return 0;
}
static void __exit exit_modules(void)
{
// remove module就應該要確保tasklet有被移除
tasklet_kill(&t1);
tasklet_kill(&t2);
tasklet_kill(t3);
}
module_init(init_modules);
module_exit(exit_modules);
Based on Kernel Version:2.6.35
參考資料:
Linux Kernel Development 3rd.
Linux Device Driver 3rd, http://www.makelinux.net/ldd3/chp-7-sect-5.shtml

