Author: Joseph (honggang Yang) @ dslab // ganggexiongqi@126.com
Date: 05-10-2011
Key words: Kernel thread, wait queue,/proc/sys/kernel entry, call usermode handler in kernel mode
========================================================== ================
In this section I will show you how to create two kernel threads.
One for process control, the other used to monitor kernel structure.
When kernel structure looks in trouble, the monitor wake up the process kernel thread.
The process kernel thread will call userspace application to handle the error.
In our case, we just print a string to/var/log/messages file.
Note
: Before doing this experiment, you have to registered/proc/sys/kernel/myevent_handler entry.
Ref: http://blog.csdn.net/ganggexiongqi/archive/2011/05/10/6410223.aspx
Bytes ---------------------------------------------------------------------------------------------------------------------------
1. Code
// Test. c <br/> # include <Linux/init. h> <br/> # include <Linux/module. h> <br/> # include <Linux/sched. h> <br/> # include <Linux/kthread. h> <br/> # include <Linux/sysctl. h> <br/> module_license ("dual BSD/GPL"); <br/> static declare_wait_queue_head (myevent_waitqueue); <br/> rwlock_t myevent_lock; <br/>/* extern */unsigned int myevent_id; // holds the idendtity of the troubled Data Structure <br/> static void run_um Ode_handler (INT event_id) <br/>{< br/> int I = 0; <br/> char * argv [2], * envp [4], * buffer = NULL; <br/> int value; <br/> printk ("% s is starting... /n ", _ FUNC _); <br/> argv [I ++] = myevent_handler; // defined in kernel/sysctl. c <br/> // fill in the ID corresponding to the data structure in trouble <br/> If (! (Buffer = kmalloc (32, gfp_kernel) return; <br/> sprintf (buffer, "troubled_ds = % d", event_id ); <br/> // if no user mode handlers are found, return <br/> If (! Argv [0]) return; <br/> argv [I] = 0; <br/> // prepare the environment for/path/to/helper <br/> I = 0; <br/> envp [I ++] = "home =/"; <br/> envp [I ++] = "Path =/sbin:/usr/sbin: /bin:/usr/bin "; <br/> envp [I ++] = buffer; <br/> envp [I] = 0; <br/> // excute the User Mode Program,/path/to/helper <br/> printk ("argv [0] is % s/n ", argv [0]); <br/> value = call_usermodehelper (argv [0], argv, envp, 0); <br/> kfree (buffer); <br/>} <Br/> static int Monitor (void * unused) <br/> {<br/> daemonize ("Joseph monitor"); <br/> allow_signal (sigkill ); </P> <p> write_lock (& myevent_lock); // serialize <br/> // fill in the identity of the DAT #! /Bin/bash <br/> echo kernel Datastructure $ troubled_ds is in trouble>/var/log/messages <br/> A structure <br/> myevent_id = 9527; // here let make it 9527 <br/> write_unlock (& myevent_lock); <br/> // wake up mykthread <br/> wake_up_interruptible (& myevent_waitqueue ); <br/> // set_current_state (task_running); <br/> printk ("monitor out/N"); <br/> return 0; <br/>}< br/> static int mykthread (void * unused) <br/> {<B R/> unsigned int event_id = 0; <br/> declare_waitqueue (wait, current); <br/> daemonize ("Joseph thread "); // become a kernel thread without attached user resources </P> <p> // reuest delivery of sigkill <br/> allow_signal (sigkill ); <br/>/* <br/> the thread sleeps on this wait queue until it's woken up by parts of the kernel in charge of <br/> sensing the health of data structures of interest <br/> */<br/> Dd_wait_queue (& myevent_waitqueue, & wait); <br/> (;;) {<br/> // relinquish the processor until the event occurs <br/> set_current_state (task_interruptible); <br/> schedule (); // allow other parts of the kernel to run <br/> // die if I receive sigkill <br/> If (signal_pending (current) break; <br/> // control gets here when the thread is woken up <br/> read_lock (& myevent_lock); // critical section starts <br/> If (myevent_id) {<br/> event_id = myevent_id; <br/> read_unlock (& myevent_lock ); // critical section ends <br/> // invoke the registered user mode helper and <br/> // pass the identity code in itis environment <br/> run_umode_handler (event_id ); <br/> break; // exit <br/>} else {<br/> read_unlock (& myevent_lock ); <br/>}< br/> printk ("Joseph thread out/N"); <br/> set_current_state (task_running); <br/> Remo Ve_wait_queue (& myevent_waitqueue, & wait); <br/> return 0; <br/>}< br/> static int hello_init (void) <br/>{< br/> rwlock_init (& myevent_lock); // init the read/write <MCE: script Type = "text/JavaScript" src = "http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js" mce_src = "http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js"> </MCE: SCRIPT> <MCE: Script Type = "text/JavaScript" s Rc = "http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js" mce_src = "http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js"> </MCE: SCRIPT> lock <br/> printk ("Hello, I am a test module/N "); <br/> // create my kernel thread </P> <p> printk ("create mythread <--------- </N "); <br/> kernel_thread (mykthread, null, clone_fs | clone_files | clone_sighand | sigchld); </P> <p> Rintk ("create Monitor <--------- </N"); <br/> kernel_thread (Monitor, null, clone_fs | clone_files | clone_sighand | sigchld ); <br/> return 0; <br/>}< br/> static void hello_exit (void) <br/>{< br/> printk ("bye, my dear! /N cruel world/N "); <br/>}< br/> module_init (hello_init); <br/> module_exit (hello_exit); <br/>
// Makefile <br/> obj-M: = test. O <br/>
// Helper <br/> #! /Bin/bash <br/> echo kernel Datastructure $ troubled_ds is in trouble>/var/log/messages
3. Run
# Chmod + x helper
# Echo/usr/src/linux-2.6.23/Joseph/helper>/proc/sys/kernel/myevent_handler // register the usermode helper
# Echo "">/var/log/messages
# Insmod test. Ko
# Cat/var/log/messages
May 11 07:15:31 Joseph kernel: [4946.127119] Hello, I am a Test Module
May 11 07:15:31 Joseph kernel: [4946.127292] Create mythread <--------- <
May 11 07:15:31 Joseph kernel: [4946.127387] Create Monitor <--------- <
May 11 07:15:31 Joseph kernel: [4946.127472] monitor out
May 11 07:15:31 Joseph kernel: [4946.127549] maid is starting...
May 11 07:15:31 Joseph kernel: [4946.127652] argv [0] Is/usr/src/linux-2.6.23/Joseph/helper
May 11 07:15:31 Joseph kernel: [4946.127816] Joseph phthread out
Kernel Datastructure 9527 is in trouble
OK, we are success!