眾所周知,核心中建立乙個核心執行緒是通過kernel_thread實現的。宣告如下:
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
我們知道,使用者態建立執行緒呼叫clone(),如果要在核心態建立執行緒,首先想到的是在核心態呼叫clone()。這是可以的。比如在init核心執行緒中就直接在核心態呼叫execve,引數為/sbin/init等等。但是還是要小心翼翼。因為系統呼叫裡會有很多引數要求是使用者態的(一般在宣告前有__user ),在呼叫一些核心函式時也會檢查引數的界限,嚴格要求引數在使用者態。一旦發現引數是在核心態,就立即返回出錯。
所以kernel_thread採用了另外一種辦法。
由於不是從使用者態進入核心的,它需要製造一種現場,好像它是通過clone系統呼叫進入核心一樣。方法是手動生成並設定乙個struct pt_regs,然後呼叫do_fork()。但是怎樣把執行緒的函式指標fn,引數arg傳進去呢?和flags不同,flags可以作為do_fork()的引數。但是fn正常情況下應該是在clone()結束後才執行的。此外,執行緒總不能長生不老吧,所以執行完fn()還要執行exit()。
所以,我們希望核心執行緒在建立後,回到核心態(普通情況下是使用者態)後,去呼叫fn(arg),最後呼叫exit()。而要去「遙控」核心執行緒在建立以後的事,只能通過設定pt_regs來實現了。
看kernel_thread的實現:
355 regs.ebx = (unsigned long) fn;
356 regs.edx = (unsigned long) arg;
這裡設定了引數fn,arg,當核心執行緒在建立以後,ebx中放的是fn,edx中放的是arg
358 regs.xds = __user_ds;
359 regs.xes = __user_ds;
360 regs.orig_eax = -1;
361 regs.eip = (unsigned long) kernel_thread_helper;
當核心執行緒在建立以後,執行的是 kernel_thread_helper函式
362 regs.xcs = __kernel_cs;
當核心執行緒在建立以後,cs暫存器的值表明當前仍然處於核心態。
363 regs.eflags = x86_eflags_if | x86_eflags_sf | x86_eflags_pf | 0x2;364
365 /* ok, create the new process.. */
366 return do_fork(flags | clone_vm | clone_untraced, 0, ®s, 0, null, null);
看來kernel_thread_helper就是我們想要的東西了。
336 __asm__(".section .text\n"
337 ".align 4\n"
338 "kernel_thread_helper:\n\t"
339 "movl %edx,%eax\n\t"
340 "pushl %edx\n\t"
341 "call *%ebx\n\t"342 "pushl %eax\n\t"343 "call do_exit\n"
344 ".previous");
首先把edx儲存到eax(不明白為什麼這麼做,因為呼叫fn後返回值就把eax覆蓋掉了)把edx(其實就是引數arg)壓入堆疊,然後呼叫ebx(也就是fn)。最後呼叫do_exit。kernel_thread_helper是不返回的。
這裡,核心通過巧妙設定pt_regs,在沒有使用者程序的情況下,在核心態建立了執行緒。
linux kernel 啟動流程簡單分析
ping linux 核心啟動的時候,總是從start kernel 這個函式作為入口。start kernel完成了對各種資源的初始化。隨後,呼叫了rest init 完成對init程序的啟動。我們用gdb跟蹤linux kernel 核心啟動可以看到。1.我們把斷點置於start kernel ...
Linux kernel路由機制分析(下)
前面已經介紹過,ip層會在輸入和輸出兩個時候去呼叫路由部分 輸入路由過程更為複雜一些也更具代表性,所以我們下面主要分析一下ip包輸入時的路由流程。下圖描述了這個流程 當有資料到達網路裝置的時候,會產生乙個中斷,中斷處理函式會呼叫驅動層的net rx函式,net rx進而產生個軟中斷進入net rx ...
載入linux kernel 的安全機制分析
system core mkbootimg mkbootimg.c 首先,一般bootimage 的結構如下 打包的時候會計算kernel,ramdisk分割槽資料的sha值,並把其存放在boot header 注意 計算的時候不包含boot header本身 sha init ctx sha up...