Linux 启动过程阅读

我阅读的代码是2.6.33.1的代码。

本文没有详细分析代码逻辑,主要是看函数执行流程。

启动过程从arch/x86/boot/header.S开始。按代码所在位置分为两部分,一部分是在boot目录下的,另一部分是在kernel目录下。

1.arch/x86/boot/header.S(Basedonbootsect.Sandsetup.S)

是在16-bit的实模式执行,因此访存是这样的:段地址:段内偏移

在header.S有一个jmpmain的命令,跳转到arch/x86/boot/main.c。

在这个main函数中,初始化许多设定,例如init_heap(),set_video()……

最后进入保护模式go_to_protected_mode(),注意,在这个函数里面有set_idt()与setup_gdt()两个操作。

看了go_to_protected_mode(),它最后一个跳转操作,现在不确定跳转到哪里。

个人感觉是跳转到arch/x86/boot/compressed/head_32.S:startup_32,这段汇编文件代码会调用decompress_kernel,在它将kernel解压后跳转到kernel代码开始执行kernel代码,kernel的入口代码是在arch/x86/kernel/head_32.S

2.在arch/x86/kernel/head_32.S在做许多初始化工作(建立gdt,idt表,开启Page机制等)之后,执行jmp*(initial_code),就跳转到了i386_start_kernel。

而在i386_start_kernel的最后调用了start_kernel,在这个函数中kernel完成了自己的许多初始化工作,包括创建init内核线程,然后最后在reset_init函数中启动了cpu_idle.

启动多个CPU的代码流程:

init/main.c:start_kernel()

|

\|/

init/main.c:rest_init

|

\|/

kernel_thread(kernel_init,NULL,CLONES_FS|CLONE_SIGHAND)

-----------------------------------------------------------------

kernel_init会被当成kernel_thread_function

kernel_thread创建地方是在init/main.c:rest_init

init/main.c:smp_init():kernel_init

|

\|/

/*calledbybootprocessortoactivatetherest*/

init/main.c:smp_init()

|

\|/

for_each_present_cpu(cpu){

if(num_onlien_cpus()>=setup_max_cpus)

break;

if(!cpu_online(cpu))

cpu_up(cpu);

}

/*Anycleanupwork*/

printk(KERN_INFO"Broughtup%ldCPUs\n",(long)num_online_cpus());

smp_cpu_done(setup_max_cpus);

--------------------------------------------------------------

cpu_up=native_cpu_up是一个回调函数。

注册地方是在:arch/x86/kernel/smp.c

structsmp_opssmp_ops={

……

.cpu_up=native_cpu_up,

……

}

arch/x86/kernel/smpboot.c:native_cpu_up(unsignedintcpu)

|

\|/

arch/x86/kernel/smpboot.c:do_boot_cpu(intapicid,intcpu)