linux內核分析-week3

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

clipboard.png

(2)執行到rest_kernel,(gdb) s 進入rest_kernel關注執行過程:函數

clipboard.png

(3)最終啓動oop

clipboard.png


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)循環,並在循環中檢測是否有調度產生,當有進程隊列新進程產生切換至新進程。線程

相關文章
相關標籤/搜索