Linux内核加载过程

2014-11-24 11:10:54 · 作者: · 浏览: 1

以32位x86,bzImge为例


grub版本为0.97


1、计算机上电


2、0xFFFFFFF0


当cpu检测reset引脚上的信号后


便将指令指针寄存器的值设置为0xfff0


——INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986, Chapter 10


此时为实模式,cpu将执行物理地址0xFFFFFFF0处的指令


访址的时候,硬件将该地址映射到BIOS的ROM中


BIOS中的指令将MBR复制到物理地址0x7c00处,并跳转到该处执行


3、0x7C00


MBR中的指令由grub安装而来,为grub-0.97/stage1/stage1.S


stage1将stage2的第1部分grub-0.97/stage2/start.S(512字节)复制到物理地址0x8000处,并跳转到该处执行


stage2将剩余部分grub-0.97/stage2/asm.S复制到物理地址0x8200处,并跳转到该处执行


...


grub-0.97/stage2/boot.c——load_image()函数


将内核映像bzImage的setup部分复制到物理地址0x90000


vmlinux部分复制到物理地址0x100000处


随后跳转到0x90200处执行


4、0x90200


arch/x86/boot/heaer.S——_start => start_of_setup


检查准备实模式堆栈,bss段清0,随后调用arch/x86/boot/main.c——main()函数


main()中使用BIOS中断读取一些硬件信息,如内存信息等


最后调用arch/x86/boot/pm.c——go_to_protected_mode()函数


go_to_protected_mode()设置段描述符,随后调用arch/x86/boot/pmjump.S——protected_mode_jump()函数


protected_mode_jump()置cr0的PE位,开启保护模式


最后跳转到code32_start,对于bzImage即物理地址0x100000,grub复制的bzImage第2部分


5、0x100000


arch/x86/boot/compressed/head_32.S——startup_32


arch/x86/boot/compressed/misc.c——decompress_kernel()解压内核


解压完成后跳转到output


6、LOAD_PHYSICAL_ADDR


根据不同的配置,解压后的代码在物理内存中的起始位置亦不同


arch/x86/kernel/head_32.S——startup_32


设置页表,置cr0的PG位,开启分页


最后跳转到arch/x86/kernel/head32.c——i386_start_kernel()函数


i386_start_kernel()中最后调用start_kernel()


7、start_kernel()


init/main.c——start_kernel()


进入c代码部分


详细的注释请参考git://github.com/kernel-digger/linux-2.6.git


错漏之处还望不吝指出