[!] 表示注释,详细信息请到文档末尾查看
宏观上:
BIOS自检——>系统引导——>启动内核——init进程
对于个人计算机,Linux从0xffff0地址的BIOS开始启动。BIOS的第一步是上电自检(POST)。上电自检的工作是检查硬件。第二步是枚举和初始化本地设备。
鉴于BIOS的不同用途,BIOS主要有两部分组成:上电自检代码和运行服务。
在上电自检完成后,上电自检代码从内存被清除,但是运行服务被保留并且对目标操作系统任然有效。
要引导一个操作系统,BIOS运行时会按照CMOS的设置定义的顺序来搜索处于活动状态并且可以引导的设备。引导设备可以为软盘,CD-ROM,硬盘的分区,网络上的设备以及U盘
.Linux一般从MBR[!1]包含初级引导程序的硬盘启动。MBR是一个512字节的扇区,为于硬盘的第一个扇区。在MBR被加载到RAM中后,由BIOS去控制它。
初级引导程序位于512字节的MBR镜像,MBR镜像有一个小型分区表和代码组成。前446字节是初级引导程序代码,包括执行代码和错误信息。接下来的64字节但是一个分区表,包含4个16字节的分区记录。MBR最后的字节定义了一个magic数字(00xaa55)。这个magic数字用来校验检查MBR。
初级引导程序主要就是找到并且加载第二阶段引导程序。其通过分区表寻找一个活的动的分区并将其 启动记录加载到RAM中执行。
第二阶段引导程序————内核引导程序
任务就是加载Linux内核和可选的初始磁盘
在x86环境中,第一阶段和第二阶段引导程序结合一起叫做Linux引导程序LILO或者GRand Unified BootLoader 简写GRUB。我们重点介绍一下GRUB引导流程。
GRUB
在系统自检通过后,就会加载磁盘上的MBR,并将控制权交给MBR中的程序(stage1),stage1执行,判断自己是否GRUB,如果是且配置了stage1_5,则加载stage1_5,否则就转去加载启动扇区,接着,stage2被加载并执行,由stage2借助stage1_5驱动文件系统,并查找grub.conf,显示启动菜单供用户选择,然后根据用户的选择或默认配置加载操作系统内核,并将控制权交给操作系统内核,由内核完成操作系统的启动,并且可以用附加的内核参数改进它。另外还能通过shell终端命令行的方式手动控制整个启动过程。
第二阶段引导程序被加载进内存后,将查询文件系统,加载默认内核镜像和initrd镜像到内存。当所有镜像准备好后,将从第二阶段跳转到内核镜像。
随着内核镜像加载到内存并且从第二阶段引导程序获得控制权,内核阶段开始了。内核镜像不是一个可以执行的内核,而是一个被压缩的内核镜像。通常是用zlib工具压缩的一个zImage(被压缩的镜像,小于512kb)或者一个bzImage(大的压缩镜像,大于512kb)。在内核镜像的头部有一个小型程序routine,其做少量的硬件设置,然后自解压内核镜像并放到高端内存。如果存在初始磁盘镜像(initrd),routine将拷贝initrd以供稍后安装使用。然后routine将调用内核开始内核启动。
当bzImage(i1386的镜像)被调用,将从汇编程序“./arch/i386/boot/head.S”的start入口开始。这段程序做些基本的硬件设置然后调用“./arch/i386/boot/compressed/head.S”中的startup_32。startup_32设置一些基本的环境(如堆栈等),并且清除BBS(Block Started by Symbol - 以符号启始的区块)。然后调用一个c函数decompress_kernel(位于./arch/i386/boot/compressed/misc.c)解压内核镜像。当内核被解压到内存后,将调用另一个位于“./arch/i386/kernel/head.S”的startup_32函数。
在这个新的startup_32函数(也叫清除程序或者进程0)中,会对页表进行初始化,并启用内存分页功能。然后会为任何可选的浮点单元(FPU)检测 CPU 的类型,并将其存储起来供以后使用。然后调用 start_kernel 函数(在 init/main.c 中),它会将您带入与体系结构无关的 Linux 内核部分。从本质上讲,这才是Linux内核的主要功能。
调用start_kernel函数之后,会调用一系列初始化函数来设置中断,执行进一步的内存配置,并加载初始RAM磁盘。最后将掉用kernel_thread(在arch/i386/kernel/process.c中)启动一个init函数,init函数是用户控件的第一个进程。最后,空闲进程将会开始执行并且进程调度器将获得控制权(当cpu调用cpu_idle后)。通过启用中断,抢占式的调度器就可以周期性地接管控制权,从而提供多任务处理能力。
在内核引导过程中,初始 RAM 磁盘(initrd)是由第 2 阶段引导程序加载到内存中的,它会被复制到 RAM 中并挂载到系统上。这个 initrd作为 RAM 中的临时根文件系统使用,并允许内核在没有挂载任何物理磁盘的情况下完整地实现引导。由于与外围设备进行交互所需要的模块可是 initrd 的一部分,因此内核可以非常小,但是仍然支持大量可能的硬件配置。在内核启动后,就可以正式装备根文件系统了(通过 pivot_root),此时会将 initrd 根文件系统卸载掉,并挂载真正的根文件系统。
initrd 函数让我们可以创建一个小型的 Linux 内核,其中包括作为可加载模块编译的驱动程序。这些可加载的模块为内核提供了访问磁盘和磁盘上的文件系统的方法,并为其他硬件提供了驱动程序。由于根文件系统是磁盘上的一个文件系统,因此 initrd 函数会提供一种启动方法来获得对磁盘的访问,并挂载真正的根文件系统。在没有硬盘的嵌入式目标中,initrd 可以是最终的根文件系统,或者也可以通过网络文件系统(NFS)来挂载最终的根文件系统。
在内核被启动并初始化后,内核启动第一个用户空间应用程序。这是调用的第一个使用标准 C 库编译的程序。在此进程之前,还没有执行任何标准的 C 应用程序。
注释:
一、MBR
MBR:Main Boot Record 主引导记录,通常称为主引导扇区。因为该扇区中,引导代码占有绝大部分的空间,故而习惯将该扇区称为MBR扇区。
主引导扇区有三部分组成(共占用512个字节):
主引导程序 即主引导记录 (占用446个字节)
可在FDISK程序中找到,他用于磁盘启动时将系统控制转给用户指定的并在分区表中登记了的某个操作系统。
磁盘分区表 (DPT,Disk Partition Table)
有四个分区表项构成(每个16个字节)
结束标志(占2个字节)
其值为AA55,存储是地位在前,高位在后,即看上去是55AA(十六进制)
二、GRUB重要文件
Linux 引导方式 1. LILO
2. GRUB