bintasong 原創做品轉載請註明出處《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000linux
0 筆記
1.1 x86計算機啓動過程
(1)CS:EIP=FFFF:0000H啓動BIOS程序
(2)BIOS例行程序檢測完硬件並完成相應的初始化以後就會尋找可引導介質.把引導程序加載到指定內存區域
(3)引導程序BootLoader開始負責操做系統初始化,而後起動操做系統。
(4)內核啓動過程包括start_kernel以前和以後,以前所有是作初始化的彙編指令,以後開始C代碼的操做系統初始化,最後執行第一個用戶態進程init。promise
1 實驗截圖
(1)b start_kernel,b rest_kernel設置斷點,運行c:ide
(2)執行到rest_kernel,(gdb) s 進入rest_kernel關注執行過程:函數
(3)最終啓動oop
2 進程執行分析
(1) 首先,進程執行start_kernel()函數,該函數是內核的入口,今後處開始利用c語言內核初始化。
(2) 在start_kernel()尾部執行rest_init(),這是內核初始化的尾聲。
(3) 進入rest_init(),建立一個內核線程ui
kernel_thread(kernel_init, NULL, CLONE_FS);atom
經過查看kernel_init函數,咱們發現如下代碼:spa
if (!try_to_run_init_process("/sbin/init") || !try_to_run_init_process("/etc/init") || !try_to_run_init_process("/bin/init") || !try_to_run_init_process("/bin/sh")) return 0;
嘗試運行磁盤上的init可執行文件
(4)進入 cpu_startup_entry
(5)進入 cpu_idle_loop,執行一個while(1)循環。操作系統
static void cpu_idle_loop(void) { while (1) { /* * If the arch has a polling bit, we maintain an invariant: * * Our polling bit is clear if we're not scheduled (i.e. if * rq->curr != rq->idle). This means that, if rq->idle has * the polling bit set, then setting need_resched is * guaranteed to cause the cpu to reschedule. */ __current_set_polling(); tick_nohz_idle_enter(); while (!need_resched()) { check_pgt_cache(); rmb(); if (cpu_is_offline(smp_processor_id())) arch_cpu_idle_dead(); local_irq_disable(); arch_cpu_idle_enter(); /* * In poll mode we reenable interrupts and spin. * * Also if we detected in the wakeup from idle * path that the tick broadcast device expired * for us, we don't want to go deep idle as we * know that the IPI is going to arrive right * away */ if (cpu_idle_force_poll || tick_check_broadcast_expired()) cpu_idle_poll(); else cpuidle_idle_call(); arch_cpu_idle_exit(); } /* * Since we fell out of the loop above, we know * TIF_NEED_RESCHED must be set, propagate it into * PREEMPT_NEED_RESCHED. * * This is required because for polling idle loops we will * not have had an IPI to fold the state for us. */ preempt_set_need_resched(); tick_nohz_idle_exit(); __current_clr_polling(); /* * We promise to call sched_ttwu_pending and reschedule * if need_resched is set while polling is set. That * means that clearing polling needs to be visible * before doing these things. */ smp_mb__after_atomic(); sched_ttwu_pending(); schedule_preempt_disabled(); } }
3 分析
在linux內核啓動過程當中,初始化代碼執行到start_kernel(),執行各類系統初始化,在start_kernel尾部執行rest_init,在rest_init中經過執行根文件系統上的init可執行文件建立了第一個pid=1的進程,這時內核初始化已經完成,0號進程蛻變成一個idel進程,該進程是一個while(1)循環,並在循環中檢測是否有調度產生,當有進程隊列新進程產生切換至新進程。線程