線程分類:內核線程、用戶線程(指不須要內核支持而徹底創建在用戶空間的線程庫,這種線程效率高,因爲Linux內核沒有輕量級進程(線程)的概念,所以不能獨立的對用戶線程進行調度,而是由一個線程運行庫來組織線程的調度)和輕量級線程(內核線程的高級抽象,大多數操做涉及到系統調用,效率不高)。html
傳統的Unix系統把一些重要的任務委託給週期性的執行進程,這些任務包括刷新磁盤高速緩存,交換出不用的頁框,維護網絡鏈接等。這些線程只運行在內核態(普通進程既能夠運行在內核態,也能夠運行在用戶態),內核線程只運行在內核態,因此只使用大於PAGE_OFFSET的線性地址空間。現代操做系統把它們的函數委託給內核線程,內核線程不受沒必要要的用戶態上下文拖累。內核線程的使用是廉價的,惟一使用的資源就是內核棧和上下文切換時保存寄存器的空間。linux
內核線程(thread)或叫守護進程(daemon)緩存
建立內核線程網絡
kernel_thread()函數建立一個新的內核線程,它接受的參數:所要執行的內核函數地址(fn)、要傳遞給函數的參數(arg)、一組clone標誌(flags)。該函數的本質上是調用數據結構
do_fork(flags|CLONE_VM|CLONE_UNTRACED),0,pregs,0,NULL,NULL); //pregs表示內核棧的地址 //CLONE_VM;避免複製進程頁表 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { struct pt_regs regs; memset(®s, 0, sizeof(regs)); regs.ARM_r1 = (unsigned long)arg; regs.ARM_r2 = (unsigned long)fn; regs.ARM_r3 = (unsigned long)do_exit; regs.ARM_pc = (unsigned long)kernel_thread_helper; regs.ARM_cpsr = SVC_MODE; return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL,NULL); }
進程0
全部進程的祖先叫作進程0,idle進程或由於歷史的緣由叫作swapper 進程。它是在linux的初始化階段從無到有的建立的一個內核線程。這個祖先進程使用靜態分配的數據結構。app
在多處理器系統中,每一個CPU都有一個進程0,只要打開機器電源,計算機的BIOS就啓動一個CPU,同時禁用其餘CPU。運行的CPU 0上的swapper進程初初始化內核數據結構,而後激活其餘的CPU,而且使用copy_process()函數建立另外的swapper進程,把0 傳遞給新建立的swapper進程做爲他們進程的PID。函數
進程1 ui
由進程0建立的內核線程執行init()函數,init() 一次完成內核的初始化。init()調用execve系統調用裝入可執行程序init ,結果,init 內核線程變成一個普通的進程,且擁有本身的每一個進程內核數據結構。在系統關閉以前,init 進程一直存活,由於它建立和監控在操做系統外層執行的全部進程的活動。atom
其餘內核線程spa
events 處理內核事件 不少軟硬件事件(好比斷電,文件變動)被轉換爲events,並分發給對相應事件感興趣的線程進行響應
ksoftirqd :處理軟中斷 硬件中斷處理每每須要關中斷,而這個時間不能太長,不然會丟失新的中斷。因此中斷處理的很大一部分工做移出,轉給不辭辛苦的ksoftirqd在中斷以外進行處理。好比一個網絡包,從網卡里面取出這個過程可能須要關中斷,可是TCP/IP協議處理就沒必要關中斷了
kblockd :管理磁盤塊讀寫
kjournald: Ext3文件系統的日誌管理 一般每一個 _已mount_ 的 Ext3分區會有一個 kjournald看管,各分區的日誌是獨立
Pdflush: dirty內存頁面的回寫 太多dirty的頁面意味着風險,好比故障時候的內容丟失,以及對突發的大量物理內存請求的響應(大量回寫會致使糟糕的響應時間)
kswapd :內存回收 確保系統空閒物理內存的數量在一個合適的範圍
aio :代替用戶進程管理io 用以支持用戶態的AIO
驅動中應用內核線程
#include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/param.h> #include <linux/jiffies.h> #include <asm/system.h> #include <asm/processor.h> #include <asm/signal.h> static pid_t thread_id; staticDECLARE_COMPLETION(exit_completion); static atomic_t time_to_quit =ATOMIC_INIT(0); int my_fuction(void *arg){ int ret; daemonize("demo-thread"); allow_signal(SIGKILL); complete(&exit_completion); while(!signal_pending(current)){ printk("jiffies is %lu/n", jiffies); set_current_stat(TASK_INTERRUPTIBLE); schedule_timeout(10 * HZ); if(atomic_read(&kthread->terminate)) { /* we receiveda request to terminate ourself */ break; } } /* for(;;) { Ret = wait_event_interruptible(wq,condition); //可採用任何同步措施 }*/ complete_and_exit(&exit_completion,1); return0; } static int __init init(void) { thread_id = kernel_thread(my_fuction,NULL, CLONE_FS | CLONE_FILES); wait_for_completion(&exit_completion); return 0; } static void __exit finish(void) { atomic_inc(&time_to_quit); kill_proc(thread_id, SIGKILL, 1); wait_for_completion(&exit_completion); printk("Goodbye/n"); } module_init(init); module_exit(finish); MODULE_LICENSE("GPL");