http://blog.csdn.net/luomoweilan/article/details/6085426
Linux内核从2.4升级到2.6之后,内核的引导过程发生了许多变化,现在研究一下Linux内核2.6版本的主要引导过程。
(参考资料:
1、《深入理解Linux内核》附录A;
2、Linux源码自带文档http://lxr.linux.no/linux+v2.6.36/Documentation/x86/boot.txt、
3、Linux源码header.S代码http://lxr.linux.no/linux+v2.6.36/arch/x86/boot/header.S
)
Linux内核2.6版本系统引导步骤:
1、开机执行BIOS代码,主要就是POST过程和初始化硬件设备;
2、BIOS代码运行结束后,BIOS把MBR(http://en.wikipedia.org/wiki/Master_boot_record)中的LILO第一部分代码(http://en.wikipedia.org/wiki/LILO_(boot_loader))和分区表加载到内存地址0X00007c00,最后跳转到LILO第一部分代码;
3、LILO第一部分代码把自己加载到内存地址0X00096a00,并在内存地址0X00098000处设置实模式堆栈,然后LILO把自己的第二部分代码加载到内存地址0X00096c00,最后跳转到LILO第二部分代码;
4、LILO第二部分代码把header.S(http://lxr.linux.no/linux+v2.6.36/arch/x86/boot/header.S)代码,一共两个512字节(boot sector和setup)分别加载到内存地址0X00090000和0X0009200,同时把Linux小内核映像加载到内存地址0X00010000或者Linux大内核映像加载到内存地址0X00100000,最后跳转到header.S代码的setup代码(240行);
5、header.S代码的setup过程调用main函数(http://lxr.linux.no/linux+v2.6.36/arch/x86/boot/main.c)(301行),最后跳转到main函数代码;
6、main函数设置临时的IDT表、GDT表、调用go_to_protected_mode()(http://lxr.linux.no/linux+v2.6.36/arch/x86/boot/pm.c#L104)函数(177行)进入保护模式,最后跳转到startup_32函数(http://lxr.linux.no/linux+v2.6.36/arch/x86/boot/compressed/head_32.S);
7、startup_32函数调用decompress_kernel()(http://lxr.linux.no/linux+v2.6.36/arch/x86/boot/compressed/misc.c)函数(151行)解压Linux内核映像到内存地址0X00100000,最后跳转到startup_32函数(http://lxr.linux.no/linux+v2.6.36/arch/x86/kernel/head_32.S);
8、startup_32函数为第一个进程0设置执行环境,包括初始化段寄存器、初始化内核页表、设置内核堆栈、加载GDT表、加载IDT表等,最后跳转到start_kernel()函数(http://lxr.linux.no/linux+v2.6.36/init/main.c#L536);
9、start_kernel函数完整的初始化了所有Linux内核,包括进程调度、内存管理、系统时间等,最后调用kernel_thread()(http://lxr.linux.no/linux+v2.6.36/arch/x86/kernel/process.c#L273)函数(437行)创建init进程;
10、init进程加载开机登录画面。
PS:
Linux内核2.4版本中内核自带引导程序bootsect.S文件,其作用相当于LILO,但是在2.6内核中,引导程序统一由LILO或GRUB等来管理系统的引导,所以在2.6内核中就没必要自带引导程序了,所以在2.6内核中把bootsect.S文件和setup.S文件合成一个文件header.S文件,header.S文件被编译成1K的代码,用来保存Linux/x86 boot protocol数据(参考Linux源码自带文档http://lxr.linux.no/linux+v2.6.36/Documentation/x86/boot.txt文件对Linux/x86 boot protocol的介绍),以及Linux内核代码的入口函数start_of_setup,这个入口函数由LILO指定跳转到start_of_setup函数。