内核经常需要在后台执行一些操作,这种任务就可以通过内核线程(kernel thread)完成--独立运行在内核空间的标准进程。内核线程和普通的进程间的区别在于内核线程没有独立的地址空间,mm指针被设置为NULL;它只在 内核空间运行,从来不切换到用户空间去;并且和普通进程一样,可以被调度,也可以被抢占。
实际上,内核线程只能由其他内核线程创建,在现有的内核线程中创建一个新的内核线程的方法:
1. kernel_thread
int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
kernel_thread通过do_fork实现:do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL)。
需要注意的是,在执行函数fn里面必须用daemonize释放资源并挂到init下,还需要用completion等待这一过程的完成。
2. kthread_run
struct task_struct *kthread_run(int (*threadfn)(void *data),void *data,const char *namefmt,...);
创建内核线程并启动。
3. kthread_create
struct task_struct *kthread_create(int (*threadfn)(void *data),void *data, const char namefmt[], ...);
int wake_up_process(struct task_struct *p);
kthread_create创建一个新的内核线程,但线程是停止的,需要用wake_up_process启动它
使用示例
1 #include <linux/kthread.h> 2 #include <linux/module.h> 3 4 #ifndef SLEEP_MILLI_SEC 5 #define SLEEP_MILLI_SEC(nMilliSec)\ 6 do { \ 7 long timeout = (nMilliSec) * HZ / 1000; \ 8 while(timeout > 0) \ 9 { \ 10 __set_current_state(TASK_INTERRUPTIBLE); \ 11 timeout = schedule_timeout(timeout); \ 12 } \ 13 }while(0); 14 #endif 15 16 static struct task_struct * MyThread = NULL; 17 18 static int MyPrintk(void *data) 19 { 20 char *mydata = kmalloc(strlen(data)+1,GFP_KERNEL); 21 memset(mydata,'\0',strlen(data)+1); 22 strncpy(mydata,data,strlen(data)); 23 while(!kthread_should_stop()) 24 { 25 SLEEP_MILLI_SEC(1000); 26 printk("%s\n",mydata); 27 } 28 kfree(mydata); 29 return 0; 30 } 31 32 static int __init init_kthread(void) 33 { 34 MyThread = kthread_run(MyPrintk,"hello world","mythread"); 35 return 0; 36 } 37 38 static void __exit exit_kthread(void) 39 { 40 if(MyThread) 41 { 42 printk("stop MyThread\n"); 43 kthread_stop(MyThread); 44 } 45 } 46 47 module_init(init_kthread); 48 module_exit(exit_kthread); 49 MODULE_LICENSE("Dual BSD/GPL");
参考:
http://blog.chinaunix.net/uid-20196318-id-136979.html http://blog.csdn.net/unbutun/article/details/4528407 http://blog.csdn.net/flyingcloud_2008/article/details/5857464