Linux引导过程与故障排除|第1章:Linux启动流程详解
Synopsis: 只有深入了解 Linux 如何启动的,才能在启动出现故障时迅速排查问题原因。POST 加电自检、根据启动顺序(Boot Sequence)去查找 MBR 引导扇区,从而读取到 bootloader(比如 GRUB) 的第一阶段引导代码,这一部分跟操作系统关系不大(通用的流程)。然后 GRUB 会借助它的 1.5 阶段代码(比如 xfs_stage1_5)识别到存放它的第二阶段代码的分区,从而开始执行第二阶段代码,并显示引导菜单。当选择了要启动的操作系统后,加载内核并执行,可能需要借助于 initial RAM disk 去识别硬件(比如 rootfs 所在硬盘),最后由内核执行第一个用户空间程序 init,主流的 init 系统包括 SysVinit、Upstart、systemd
1. BIOS
当你按下电源键的那一刻起,计算机的的启动就开始了。Intel x86 系列的 CPU
可以分别在 16 位 实模式(Real mode)
和 32 位 保护模式(Protected mode)
下运行。为了向后兼容,Intel 将所有 x86 系列的 CPU(包括最新型号的 CPU)的硬件都设计为加电即进入 16 位实模式运行
实模式的特征是 CPU 的寻址空间只有 2 ^ 20 = 1048576 Bytes = 1 MB,且硬件不支持分布机制和实时多任务
同时,Intel CPU 还会借助于 复位向量(reset vector)
,让 CPU 在加电瞬间强行将 CS
的值设置为 0xFFFF
,将 IP
的值设置为 0x0000
,如此一来 CS:IP
就指向了 0xFFFF0
(CS * 16 + IP) 这个内存地址,而 BIOS(Basic Input/Output System,基本输入/输出系统)
程序的入口地址恰恰就是 0xFFFF0
!也就是说,BIOS 程序的第一条指令就设计在这个位置上
BIOS
与CMOS
之间的联系与区别:
BIOS
是一段程序,存储在电可擦除可编程只读存储器(EEPROM)
中,EEPROM 是闪存芯片,在特定的条件下是可写的,因此我们可以更新升级BIOS
程序,断电后内容不会丢失。但在谈到主板上存储BIOS
的闪存芯片时,业内人士把它看作ROM(Read Only Memory,只读存储器)
- 用户可以修改
BIOS
程序的相关设置项,例如设置硬件时间、IPMI地址、启动顺序等,而设置结果就保存在CMOS
中 CMOS
是RAM(Random Access Memory,随机存储器)
,RAM
的特点是加电状态下可任意读、写,断电后内容丢失(比如内存),但CMOS
由主板上的充电电池供电,即使计算机断电,里面的内容也不会丢失。给CMOS
放电,即取下主板上的电池再插回去,就可以清空CMOS
中保存的内容
1.1 POST
BIOS
程序的代码量并不大,却非常精深。首先它会检查计算机硬件能否满足基本的运行条件,这个过程叫作 POST(Power-On Self-Test,加电自检)
,它主要针对计算机硬件如内存、硬盘、RAID卡、显卡等进行检测, 例如内存不能正常工作的话,整个启动过程将终止。加电自检的检查速度极快,甚至感受不到它的存在
1.2 Boot Sequence
加电自检通过后,BIOS
会依次初始化其它硬件设备,比如显卡、SAS3 HBA卡、3108 RAID卡等。然后,BIOS
会按照类似下图中的 启动顺序(Boot Sequence)
,逐一地去查找这些硬盘、光盘、LiveCD、U盘、网络 PXE 引导等设备(底层原理是通过 INI 13
中断),并判断是否为 可引导设备(bootable device)
。例如你插入一张光盘,但是它并不是可启动的光盘,就没法引导启动,BIOS
就会跳过它继续查找下一个引导设备,如果最后都没有找到,则会在显示器上显示 Operating System not found
各厂商生产的计算机进入
BIOS
设置界面的按键不同,一般为F2
/Del
等
2. MBR
如何判断当前设备是 可引导设备
呢?BIOS
会读取设备的第一个扇区(0 磁头 0 柱面 0 扇区)到内存中,默认每个扇区 sector
的大小为 512 Bytes
,如果这 512 字节的最后两个字节是 0x55AA
,表明该扇区是 引导扇区(boot sector)
,则 BIOS
认为该设备可以用于启动(也可能后续无法从该设备启动),并将控制权移交给它;否则,继续查找下一个设备
该扇区也叫 主引导记录(MBR, Master Boot Record)
,它的结构如下:
3. Bootloader (GRUB legacy)
常见的 引导加载程序(bootloader)
:
- 古老的
LILO(LInux LOader)
,现在几乎没有发行版使用了 - CentOS 5/6:
GRUB(GRand Uniform Bootloader)
0.x 版本,也叫GRUB legacy
- CentOS 7:
GRUB 2
1.x 之后的版本,目前最新为 2.02 - Linux 发行版ISO 或 LiveCD: 一般使用
isolinux
- PXE 网卡启动: 一般使用
syslinux
- Windows:
ntloader
本文以 GRUB legacy
为例讲解
3.1 GRUB 三段式引导
由于 引导加载程序
很大,而上图中 MBR
中最前面的引导代码只占 440 字节,这太小了,所以它只包含引导加载程序的第一阶段代码(stage1
)
第二阶段代码(stage2
)一般存放在硬盘的 /boot/grub
目录下(可能是单独的硬盘分区),假设该分区使用 ext4
文件系统格式,那么 GRUB
的第一阶段代码想读取第二阶段代码的话,就必须先加载该文件系统的驱动,446 字节空间根本放不下,所以就出现了 stage1_5
,它位于 MBR
那个扇区与第一个硬盘分区之间(历史原因,第一个分区是从 63
号扇区开始,即 MBR
和第一个分区之间有 62 sectors = 31744 Bytes = 31 KB
空闲的空间)
由于 stage1_5
可以容纳的代码量较大,因此它有足够的空间来包含一些常见的 文件系统驱动
程序,例如标准的 e2fs_stage1_5
、xfs_stage1_5
、iso9660_stage1_5
等。回顾 Linux 安装时,最后一步除了把 GRUB 的 stage1
安装到 MBR
中以外,还会根据 /boot
分区的文件系统类型,比如是 ext4
,则把 e2fs_stage1_5
放到 MBR
后面的 31 KB
空间内
所以当 stage1
定位和加载了 stage1_5
之后,就能读取到引导加载程序的 stage2
,从而在屏幕上显示 引导菜单
等信息,如下所示:
0 条评论
评论者的用户名
评论时间暂时还没有评论.