第一阶段:BIOS
计算机加电后,有一个特殊的硬件电路在CPU的一个引脚上产生一个RESET逻辑值,把处理器的一些寄存器设置成固定的值,并执行在物理地址0XFFFFFFF0处的代码(BIOS)。
BIOS的工作内容:
1. 上电自检。对计算机硬件执行一系列测试,检测设备是否正常工作。
2. 初始化硬件设备。
3. 搜索一个操作系统来启动。
4. 把第一个扇区的内容拷贝到内存中物理地址0X00007C00开始的位置,然后跳转到这个地址处,开始执行刚才装载进来的代码。
第二阶段:引导装入程序
引导装入程序是由BIOS用来把操作系统内核映像长在到RAM中所调用的一个程序。一般有LILO和GRUB。
LILO执行的主要步骤:
1. 显示“loading”信息。
2. 从磁盘装入内核映像的初始部分,即将内核映像的第一个512字节从地址0x00090000开始存入RAM中,而将setup()函数的代码从地址0x00090200开始存入RAM中。
3. 从磁盘中装载其余的内核映像。
4. 跳转到setup()代码。
第三阶段:setup()函数
汇编语言函数,主要功能是初始化大部分硬件设备,虽然在BIOS阶段已经初始化了大部分硬件设备,但是LINUX不依赖于BIOS,以自己的方式重新初始化设备以增强可移植性和健壮性。
跳转到startup_32()汇编语言函数。
第四阶段:startup_32()函数
有两个不同的startup_32()函数,此处我们指的是arch/i386/boot/compressed/head.S文件中实现的那个。
主要执行以下操作:
1. 初始化段寄存器和一个临时堆栈。
2. 清零eflags寄存器的所有位。
3. 用0填充内核未初始化数据区。
4. 调用decompress_kernel()函数来解压内核映像。一般解压后的内核放在物理地址0x00100000处。
5. 跳转到物理地址0x00100000。
解压后的内核映像以包含在arch/i386/kerner/head.S中的另一个startup_32()函数开始。
该函数执行完以后,跳转到start_kernel()函数执行。
第五阶段:start_kerner()函数
这个函数完成linux内核的初始化工作。
主要操作有:
1. 调用sched_init()函数初始化调度程序。
2. 调用build_all_zonelists()函数初始化内存管理区。
3. 调用page_alloc_init()函数来初始化伙伴系统分配程序。
4. 调用trap_init()函数完成IDT初始化。
5. 调用time_init()函数来初始化系统日期和时间。
6. 调用kmem_cache_init()函数来初始化slab分配器。
7. 调用calibrate_delay()函数以确定CPU时钟的速度。
8. 调用kernel_thread()函数为进程1创建内核进程。这个内核进程又会创建其他的内核进程并执行sbin/init程序。
在start_kernel()开始执行后会显示版本信息,除此之外,在init程序和内核线程执行的最后阶段还会显示很多其他信息。最后就会在控制台上出现熟悉的登录提示符了。