1

bintasong 原创作品转载请注明出处《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

0 笔记
1.1 x86计算机启动过程
(1)CS:EIP=FFFF:0000H启动BIOS程序
(2)BIOS例行程序检测完硬件并完成相应的初始化之后就会寻找可引导介质.把引导程序加载到指定内存区域
(3)引导程序BootLoader开始负责操作系统初始化,然后起动操作系统。
(4)内核启动过程包括start_kernel之前和之后,之前全部是做初始化的汇编指令,之后开始C代码的操作系统初始化,最后执行第一个用户态进程init。


1 实验截图
(1)b start_kernel,b rest_kernel设置断点,运行c:

clipboard.png

(2)执行到rest_kernel,(gdb) s 进入rest_kernel关注执行过程:

clipboard.png

(3)最终启动

clipboard.png


2 进程执行分析
(1) 首先,进程执行start_kernel()函数,该函数是内核的入口,从此处开始利用c语言内核初始化。
(2) 在start_kernel()尾部执行rest_init(),这是内核初始化的尾声。
(3) 进入rest_init(),创建一个内核线程

kernel_thread(kernel_init, NULL, CLONE_FS);

通过查看kernel_init函数,我们发现以下代码:

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)循环,并在循环中检测是否有调度产生,当有进程队列新进程产生切换至新进程。


binta
73 声望5 粉丝

The Magic Words are Squeamish Ossifrage


引用和评论

0 条评论