- 論壇徽章:
- 0
|
回復(fù) #17 frank_seng 的帖子
#
Linux kernel啟動時第一次進(jìn)入cpu_idle的簡單分析,下圖為其流程圖,從圖中可知,由于current(也就是init_task)的need_resched現(xiàn)在等于1,故立刻開始執(zhí)行schedule();
|
+-------------->|
| +------------>|
| | v
| | _,,-,,_
| | ,,.-'`` ``'-.,,
| | current->need_resched==0? ---+
| | `'-.,, ,,.-'`` |
| | ``'--'`` | N
| | Y| |
| | v v
| | +--------------+ +--------------+
| | | idle() | | schedule() |
| | +--------------+ +--------------+
| | | |
| +-------------+ |
+--------------------------------+
- 現(xiàn)在就兩個進(jìn)程:init_task和new_task(init),很顯然schedule->switch_to會選中new_task開始執(zhí)行,同時將init_task.need_resched置0;
- new_task 的esp、eip在(3)中已經(jīng)被設(shè)置好了,故esp寄存器被恢復(fù)為new_task->thread.esp,也就是 union2.pt_regs底部;eip寄存器被恢復(fù)為new_task->thread.eip也就是ret_from_fork, new_task從ret_from_fork處開始執(zhí)行,由于new_task系統(tǒng)堆棧中保存的用于返回的EIP是從原來的init_task中復(fù)制過來的,而且new_task->need_resched=0,因此new_task返回到kernel_thread中;
- 隨后在kernel_thread中,此時將esp和esi比較(esi中保存的是剛進(jìn)kernel_thread時的esp),對于new_task而言,很明顯,這里是不相等的,esp為new_task堆棧指針地址,esi為init_task堆棧指針地址;
- 執(zhí)行函數(shù)init(),在init中會執(zhí)行execve("/sbin/init")【內(nèi)核中的execve宏定義見_syscall3】,也就是 sys_excve("/sbin/init),new_task完全被/sbin/init替代,其永遠(yuǎn)不會再回到kernel_thread了,在 sys_execve中會構(gòu)造用戶空間,/sbin/init也會啟動一些列應(yīng)用層初始化進(jìn)程,系統(tǒng)主要起始進(jìn)程啟動成功;
- 關(guān)于kernel_thread需要說明的是:如果這里不是init()函數(shù),而是一個普通函數(shù),則kernel_thread在執(zhí)行完該普通函數(shù)后,執(zhí)行sys_exit退出并釋放該任務(wù);
|
|