Использование тасклетов (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);