Использование тасклетов (tasklet_struct) для запуска функций отложенных действий.
Тасклеты (tasklet_struct), как и очереди задач, реализуют механизм выполнения отложенных действий. При этом тасклеты (tasklet_struct) выполняются в softirq прерываниях, поэтому если в коде имеется секция BUG_ON(in_interrupt()), то использование тасклета (tasklet_struct) там невозможно.
Пример использования тасклета (tasklet_struct) со статическим объявлением и передачей параметров в функцию тасклета ( в качестве параметра передаётся строка ):
/* * stat_tasklet.c - пример использования такслета * со статическим объявлением */ #include <linux/module.h> #include <linux/workqueue.h> #include <linux/interrupt.h> #define DRIVER_AUTHOR "noname author" #define DRIVER_DESC "static tasklet" char tmpVar[] = "hello tasklet"; /* функция, которую требуется вызвать в отложенном режиме */ static void my_tasklet_function(unsigned long data){ printk("call tasklet function\n"); printk ("tasklet data: %s\n",(char *)data); } /* объявляется тасклет * первый аргумент - имя тасклета * второй аргумент - имя функции которую нужно отложенно выполнить * третий аргумент - переменная которая передаётся в функцию */ DECLARE_TASKLET (tst_tasklet, my_tasklet_function, (unsigned long) &tmpVar); /* функция, которая вызывается при загрузке модуля */ static int __init init_stat_tasklet(void){ printk(KERN_ALERT "Hello, static tasklet\n"); /* помещение тасклета в очередь на выполнение */ tasklet_schedule(&tst_tasklet ); return 0; } static void __exit cleanup_stat_tasklet(void){ printk(KERN_ALERT "Goodbye, static tasklet\n"); } module_init(init_stat_tasklet); module_exit(cleanup_stat_tasklet); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC);
Также как и с очередями задач, тасклеты можно вызывать используя динамическое объявление.
Пример использования тасклета (tasklet_struct) с динамическим объявлением и передачей параметров в функцию тасклета (в качестве параметра передаётся число char):
/* * dynam_tasklet.c - пример использования такслета * с динамическим объявлением */ #include <linux/module.h> #include <linux/workqueue.h> #include <linux/interrupt.h> #include <linux/slab.h> #define DRIVER_AUTHOR "noname author" #define DRIVER_DESC "dynamic tasklet" char tmpVar=55; /* функция, которую требуется вызвать в отложенном режиме */ static void my_tasklet_function(unsigned long data){ printk("call tasklet function\n"); printk ("tasklet data: %d\n",*(char *)data); } //DECLARE_TASKLET (tst_tasklet, my_tasklet_function, (unsigned long) &tmpVar); /* функция, которая вызывается при загрузке модуля */ static int __init init_dynam_tasklet(void){ printk(KERN_ALERT "Hello, dynamic tasklet\n"); /* объявление указателя на тасклет */ struct tasklet_struct *tst_tasklet; /* выделение памяти под структуру */ tst_tasklet = kmalloc( sizeof(struct tasklet_struct), GFP_KERNEL ); /* объявляется тасклет * первый аргумент - имя тасклета * второй аргумент - имя функции которую нужно отложенно выполнить * третий аргумент - переменная которая передаётся в функцию */ tasklet_init (tst_tasklet, my_tasklet_function, &tmpVar); /* помещение тасклета в очередь на выполнение */ tasklet_schedule(tst_tasklet); return 0; } static void __exit cleanup_dynam_tasklet(void){ printk(KERN_ALERT "Goodbye, dynamic tasklet\n"); } module_init(init_dynam_tasklet); module_exit(cleanup_dynam_tasklet); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC);