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-03-24 17:56:44 发布