14 - Opóźnione wykonywanie zadań

tasklet.c

tasklet.c
/* Tasklety wykorzystywane są przy obsłudze przerwań, tu natomiast zadanie
   tworzne jest podczas inicjowania modułu. */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marcin Bis");
MODULE_DESCRIPTION("Pierwszy modul");
 
char my_tasklet_data[]="tasklet executed";
 
/* Dolna połówka */
void my_tasklet_function(unsigned long data)
{
  printk(KERN_INFO "%s\n", (char *)data);
  return;
}
 
DECLARE_TASKLET(my_tasklet, my_tasklet_function, 
                (unsigned long) &my_tasklet_data);
 
static int __init my_tasklet_init(void)
{
  /* Zleć wykonanie dolnej połówki */
  tasklet_schedule(&my_tasklet);
  return 0;
}
module_init(my_tasklet_init);
 
static void __exit my_tasklet_cleanup(void)
{
  /* Przed wyjściem wyrejestruj wszystkie niedokończone jeszcze zadania */
  tasklet_kill(&my_tasklet);
}
module_exit(my_tasklet_cleanup);

workqueue.c

workqueue.c
/*
Moduł tworzy kolejkę zadań, która jest bardzo rozbudowanym mechanizmem opóźnionego
wykonywania funkcji.
 
                                                                            Kontekst
                                                                            procesu
 Kontekst                                                                /> funkcja
przerwania                                                              /   obsługi
                                                                       /
 funkcja             struct                struct                     /     funkcja
 obsługi       ---> work_struct --->  workqueue_struct ---> events/X -----> obsługi
przerwania                                                   wątek    \
                                                             jądra     \    funkcja
 górna                                                                  \-> obsługi
połówka                                                                     dolna
                                                                            połówka
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marcin Bis");
MODULE_DESCRIPTION("Workqueue");
 
static struct workqueue_struct *my_wq;
 
typedef struct {
  struct work_struct my_work;
  int x;
} my_work_t;
 
my_work_t *job1, *job2;
 
static void my_wq_function(struct work_struct *work)
{
  my_work_t *my_work = (my_work_t *)work;
  printk("my_work.x %d\n", my_work->x);
  kfree((void *)work);
  return;
}
 
int __init wq_init(void)
{
  int ret;
  my_wq = create_workqueue("my_queue");
  if (my_wq) {
    /* Zakolejkuj zadanie */
    job1 = (my_work_t *)kmalloc(sizeof(my_work_t), GFP_KERNEL);
    if (job1) {
      INIT_WORK((struct work_struct *)job1, my_wq_function);
     /* Inne metody:
      INIT_DELAYED_WORK(work, func);
      INIT_DELAYED_WORK_DEFERRABLE(work, func);
     */
      job1->x = 1;
      ret = queue_work(my_wq, (struct work_struct *)job1);
     /*
      int queue_work(struct workqueue_struct *wq, struct work_struct *work);
      int queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work);
      int queue_delayed_work( struct workqueue_struct *wq,
			struct delayed_work *dwork, unsigned long delay );
      int queue_delayed_work_on( int cpu, struct workqueue_struct *wq,
			struct delayed_work *dwork, unsigned long delay );
     */
    }
 
    /* Drugie zadanie */
    job2 = (my_work_t *)kmalloc(sizeof(my_work_t), GFP_KERNEL);
    if (job2) {
      INIT_WORK((struct work_struct *)job2, my_wq_function);
      job2->x = 2;
      ret = queue_work(my_wq, (struct work_struct *)job2);
    }
  }
  return 0;
}
module_init(wq_init);
 
void __exit wq_clean(void)
{
  flush_workqueue(my_wq);
  destroy_workqueue(my_wq);
}
module_exit(wq_clean);

Makefile

Makefile
obj-m += tasklet.o
obj-m += workqueue.o
 
all:
	make -C /lib/modules/$(shell uname -r)/build \
		SUBDIRS=$(shell pwd) modules
 
clean:
	make -C /lib/modules/$(shell uname -r)/build \
		SUBDIRS=$(shell pwd) clean
ostatnio zmienione: 2011/06/16 16:07