thread 可以被認為是使用者程式當中的一個執行流程,Multi-thread process當中還可以包含更多的執行流程!
而在 Unix* 作業系統底下還存在一種特殊的 thread 稱之為 kernel thread(核心執行緒),
kernel thread 未必只有執行核心的某種功能,亦可能與某個 User program 有關係,
然而 kernel thread 與一般的 process 比較起來具有較輕鬆的環境切換代價,通常稱之為 Context switch,
它發生在 process 調用 scheduler 進行排程的時候,要把當前 process 所用到的 CPU 資訊給儲存起來,
包含了 Register(暫存器)等等。
因為 thread 屬於簡單的 execution flow 所以每當要進行 Context switch 時,要儲存的資料會比較少,因此負擔會輕一些!
kernel thread 的特性如下:
- 運作在 Kernel space & Kernel Mode
- 不與 User 進行互動,因此不需要終端機設備
- 於系統啟動時期建立,存活到系統關閉為止
在傳統的 Unix 作業系統,偶爾會將一些關鍵的任務委派給執行中的 process ,比如像是 Page swapping、服務網路連線、Disk cache等等之類的。
不過現在的作業系統大多都會把這些任務放在背景去執行,避免使用線性的方式而得到不好的效能,
特別是 kernel thread 只運作在 kernel space 之中,因此這些工作最好都交給 kernel thread 來做最適當不過了!
kernel_thread()函式可以用來建立新的 kernel thread,函式存在 linux/arch/i386/kernel/process.c 之中:
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
struct pt_regs regs;memset(®s, 0, sizeof(regs));
regs.ebx = (unsigned long) fn;
regs.edx = (unsigned long) arg;
regs.xds = __USER_DS;
regs.xes = __USER_DS;
regs.xfs = __KERNEL_PERCPU;
regs.orig_eax = -1;
regs.eip = (unsigned long) kernel_thread_helper;
regs.xcs = __KERNEL_CS | get_kernel_rpl();
regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0×2;
/* Ok, create the new process.. */
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
}
EXPORT_SYMBOL(kernel_thread);
可以看到 kernel_thread() 函式的參數包括:
- fn:要被執行的核心函式位置
- arg:該函式的引數
- 第三個是一組 Clone flags
而在 kernel_thread() 之中可以看到調用了 do_fork() 建立新的process,然而該參數的意義如下:
- CLONE_VM:避免浪費時間在複製呼叫這個函式的行程的 Page 對映表
- CLONE_UNTRACED:確保新的 kernel thread 不會被任何行程追蹤
- pregs 指向了 ®s 這個結構的位址,當中包含了相應於 Kernel Mode Stack 裡面的位址
一些典型的例子,例如 Swapper, init process 都是屬於 kernel thread,雖然在Linux 使用 kernel thread 地方很有限,但是卻是用來執行幾個重要的核心功能。
Ref: Understanding the Linux Kernel 3e