Linux Kernel programming (scheduling task) 8

Source: Internet
Author: User
Linux Kernel programming (scheduling task) 8-Linux general technology-Linux programming and kernel information. The following is a detailed description. 10. Schedule a task
Often, we have "Chores" that must be done regularly or frequently ". If this task is completed by a process, we can put it into the crontab file. If this task is completed by a kernel module, we have two possible options. The first is to put a process into the crontab file, which will wake up the module through a system call when necessary, such as opening a file. However, this is very inefficient. We need to run a new process outside the crontab and read a new execution table into the memory. All these are just to wake up a kernel module in the memory.
We do not need to do this. We can create a function that is called during every interruption of time. The method is to create a task, which is contained in a struct tq_struct, and contains a pointer to the function entry address. Then, we use queue_task to put this task into a task list called tq_timer, which is a list of tasks to be executed during the next interruption. Because we want this function to be continuously executed, we need to put it back in tq_timer every call for the next interruption.
Another point is worth remembering. When a module is deleted by rmmod, its index counter is checked first. If the value is 0, module_cleanup is called. Then, this module and all its functions are deleted from the memory. No one checks whether the clock task list still contains pointers to these functions, but it is unavailable now. A long time later (from the computer's perspective, it may be 1% seconds in human eyes), the kernel had a clock interruption and tried to call all functions in the task list. Unfortunately, this function does not exist. In most cases, its memory is not used yet, and you get an extreme error message. However, if other codes are in the same address, the situation will be very bad. Unfortunately, we do not have a method to deregister a task from the task list.
Since the cleanup_module function cannot return an error horse (it is a void function), the solution is not to let it return. Instead, call sleep_on or module_sleep_on (note 10.1) to suspend the rmmod process. Before that, it sets a variable to notify the function called when the clock is interrupted to stop appending itself. Then, when the next clock is interrupted, the rmmod process will be awakened, and our functions are no longer in the queue, so that we can safely delete the module.
Ex sched. c

/* Sched. c-scheduale a function to be called on
* Every timer interrupt .*/



/* Copy right (C) 1998 by Ori Pomerantz */


/* The necessary header files */

/* Standard in kernel modules */
# Include/* Were doing kernel work */
# Include/* Specifically, a module */

/* Deal with CONFIG_MODVERSIONS */
# If CONFIG_MODVERSIONS = 1
# Define MODVERSIONS
# Include
# Endif

/* Necessary because we use the proc fs */
# Include

/* We scheduale tasks here */
# Include

/* We also need the ability to put ourselves to sleep
* And wake up later */
# Include

/* In 2.2.3/usr/include/linux/version. h between des
* Macro for this, but 2.0.35 doesnt-so I add it
* Here if necessary .*/
# Ifndef KERNEL_VERSION
# Define KERNEL_VERSION (a, B, c) (a) x 65536 + (B) * 256 + (c ))
# Endif



/* The number of times the timer interrupt has been
* Called so far */
Static int TimerIntrpt = 0;


/* This is used by cleanup, to prevent the module from
* Being unloaded while intrpt_routine is still in
* The task queue */
Static struct wait_queue * WaitQ = NULL;

Static void intrpt_routine (void *);


/* The task queue structure for this task, from tqueue. h */
Static struct tq_struct Task = {
NULL,/* Next item in list-queue_task will do
* This for us */
0,/* A flag meaning we havent been inserted
* Into a task queue yet */
Intrpt_routine,/* The function to run */
NULL/* The void * parameter for that function */
};



/* 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 .*/
Static void intrpt_routine (void * irrelevant)
{
/* Increment the counter */
TimerIntrpt ++;

/* If cleanup wants us to die */
If (WaitQ! = NULL)
Wake_up (& WaitQ);/* Now cleanup_module can return */
Else
/* Put ourselves back in the task queue */
Queue_task (& Task, & tq_timer );
}




/* Put data into the proc fs file .*/
Int procfile_read (char * buffer,
Char ** buffer_location, off_t offset,
Int buffer_length, int zero)
{
Int len;/* The number of bytes actually used */

/* This is 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 shoshould always be no.
*/
If (offset> 0)
Return 0;

/* Fill the buffer and get its length */
Len = sprintf (my_buffer,
"" Timer was called % d times so far "",
TimerIntrpt );
Count ++;

/* Tell the function which called us where
* Buffer is */
* Buffer_location = my_buffer;

/* Return the length */
Return len;
}


Struct proc_dir_entry Our_Proc_File =
{
0,/* Inode number-ignore, it will be filled
* Proc_register_dynamic */
5,/* Length of the file name */
"" Sched "",/* The file name */
S_IFREG | S_IRUGO,
/* File mode-this is a regular file which can
* Be read by its owner, its group, and everybody
* Else */
1,/* Number of links (directories where
* The file is referenced )*/
0, 0,/* The uid and gid for the file-we give
* It to root */
80,/* The size of the file reported by ls .*/
NULL,/* funich which can be done on
* Inode (linking, removing, etc.)-we dont
* Support any .*/
Procfile_read,
/* The read function for this file, the function called
* When somebody tries to read something from it .*/
NULL
/* We cocould have here a function to fill
* Files inode, to enable us to play
* Permissions, ownership, etc .*/
};


/* Initialize the module-register the proc file */
Int init_module ()
{
/* Put the task in the tq_timer task queue, so it
* Will be executed at next timer interrupt */
Queue_task (& Task, & tq_timer );

/* Success if proc_register_dynamic is a success,
* Failure otherwise */
# If LINUX_VERSION_CODE> KERNEL_VERSION (2, 2, 0)
Return proc_register (& proc_root, & Our_Proc_File );
# Else
Return proc_register_dynamic (& proc_root, & Our_Proc_File );
# Endif
}


/* Cleanup */
Void cleanup_module ()
{
/* Unregister our/proc file */
Proc_unregister (& proc_root, Our_Proc_File.low_ino );

/* Sleep until intrpt_routine is called one last
* Time. This is necessary, because otherwise well
* Deallocate the memory holding intrpt_routine and
* Task while tq_timer still references them.
* Notice that here we dont allow signals
* Interrupt us.
*
* Since WaitQ is now not NULL, this automatically
* Tells the interrupt routine its time to die .*/
Sleep_on (& WaitQ );
}
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.