Scheduling task example. /* sched.c */ #include <linux/kernel.h> /*We're doing kernel work*/ #include <linux/module.h> /*Specifically, a module*/ #include <linux/proc_fs.h> /*Necessary because we use the proc fs*/ #include <linux/workqueue.h> /*We scheduale tasks here*/ #include <linux/sched.h> /*We need to put ourselves to sleep and wake up later*/ #include <linux/init.h> /*For __init and __exit*/ #include <linux/interrupt.h> /*For irqreturn_t*/ struct proc_dir_entry *Our_Proc_File; #define PROC_ENTRY_FILENAME "sched" #define MY_WORK_QUEUE_NAME "WQsched.c" /* * The number of times the timer interrupt has been called so far */ static int TimerIntrpt=0; static void intrpt_routine(void*); static int die=0; /*set this to 1 for shut down*/ /* * The work queue structure for this task, from workqueue.h */ static struct workqueue_struct *my_workqueue; static struct work_structTask; static DECLARE_WORK(Task,intrpt_routine,NULL); /* * This function will be called on every timer interrupt. Notice the void* * pointer - task functions can be used for more than one purpose, each time * getting a different parameter. */ staticvoidintrpt_routine(void*irrelevant) { /* * Increment the counter */ TimerIntrpt++; /* * If cleanup wants us to die */ if(die==0) queue_delayed_work(my_workqueue,&Task,100); } /* * Put data into the proc fs file. */ ssize_t procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data) { int len; /*The number of bytes actually used*/ /* * It's static so it will still be in memory * when we leave this function */ static char my_buffer[80]; static int count=1; /* * We give all of our information in one go, so if the anybody asks us * if we have more information the answer should always be no. */ if(offset>0) return0; /* * Fill the buffer and get its length */ len=sprintf(my_buffer,"Timer called%d times so far/n",TimerIntrpt); count++; /* * Tell the function which called us where the buffer is */ *buffer_location=my_buffer; return len; } int __init init_module(){ int rv = 0; /* * Put the task in the work_timer task queue, so it will be executed at * next timer interrupt */ my_workqueue=create_workqueue(MY_WORK_QUEUE_NAME); queue_delayed_work(my_workqueue,&Task,100); Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL); printk(KERN_INFO "Trying to create /proc/test:/n"); if (Our_Proc_File == NULL){ rv= -ENOMEM; remove_proc_entry("test", &proc_root); } else{ Our_Proc_File->read_proc = procfile_read; Our_Proc_File->owner = THIS_MODULE; Our_Proc_File->mode = S_IFREG | S_IRUGO; Our_Proc_File->uid = 0; Our_Proc_File->gid = 0; Our_Proc_File->size = 80; printk(KERN_INFO "Success!/n"); } return rv; } void __exit cleanup_module(){ remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root); printk(KERN_INFO "/proc/%sremoved/n", PROC_ENTRY_FILENAME); die=1; /*keep intrp_routine from queueing itself*/ cancel_delayed_work(&Task); /*no"newones"*/ flush_workqueue(my_workqueue); /*wait till all "oldones" finished*/ destroy_workqueue(my_workqueue); /* * Sleepuntilintrpt_routineiscalledonelasttime.Thisis * necessary, because otherwise we'll deallocate the memory holding * intrpt_routine and Task while work_timer still references them. * Notice that here we don't allow signals to interruptus. * * Since WaitQ is now not NULL, this automatically tells the interrupt * routine it's time to die. */ } MODULE_LICENSE("GPL");
2008 May 14th Wednesday (五月 十四日 水曜日)
最新推荐文章于 2021-12-18 14:48:30 发布