核心經常需要在後台執行一些操作,這種任務就可以通過核心線程(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 #endif15 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