透彻的了解Linux启动流程是非常关键的知识点,只有了解了这部分内容,才会在Linux出现系统级别的错误时能够非常冷静的面对以及快速的排错。
Linux启动流程
第一阶段
- BIOS不是操作系统的职责范围
- BIOS是硬件的功能,属于firmware
- BIOS存储于ROM,不需要强电就可以实现数据保存
- 更改BIOS如启动顺序保存在一种特定的RAM中,为了保证断电后实际更改保存,通过BIOS上加电池来解决
- 在BIOS可以选择启动顺序(硬盘,光盘,网络等)
- 如果选择BIOS从硬盘启动,硬盘的必须是MBR分区,相应的支持的硬盘最大为2TB
- 替代BIOS的是UEFI(Unified Extensible Firmware Interface),通常配合硬盘分区类型GPT,支持最大硬盘8ZB
- 一旦BIOS找到硬盘MBR分区中的引导程序bootloader,就把后续工作转交给bootloader
第二阶段
- bootloader把内核加载到内存
- 但凡读取了一个设备的MBR,如果MBR中的bootloader损坏,无法正常启动,操作系统不会再去读第二个设备的MBR,这也正是由于bootloader损坏,我们需要更改BIOS的启动顺序从光盘启动去修复硬盘中bootloader的原因
- 一旦Kernel装载完毕,Bootloader退出工作,把后续的工作交给Kernel
Bootloader详解:
Bootloader是一个程序,不属于任何的操作系统,但是由操作系统安装时提供。常见的有微软的ntloader,Linux的两种常用的bootloader:
- LILO:大于8G的硬盘不支持,在嵌入式系统中常用
- GRUB:GRand Unified Bootloader,目前有两个主流版本grub-0.97和grub2-2.02,下图就是在安装Linux过程中创建bootloader的过程
GRUB三个阶段详解:
GRUB是一个程序,需要安装在MBR分区的bootloader位置上来引导操作系统的启动,MBR446bytes的空间没有办法展示GRUB的丰富的特性,由此引入GRUB三阶段概念。
GRUB Stage1:MBR
作用:引导GRUB的第二阶段
GRUB Stage1.5:
作用:识别常见的不同类型的文件系统,mbr之后的扇区,让stage1中的bootloader能识别stage2所在的分区上的文件系统
GRUB stage2:
作用:位于内核所在的分区的/boot/grub/stage2,借助grub.conf配置文件,来实现更强大的功能
grub.conf详解:
default=0 : 设定默认启动的title编号,从0开始
timeout=5 : 等待用户选择的超时时长,单位是秒
splashimage : grub的背景图片
hiddenmenu : 隐藏菜单(删除之后不再隐藏)
title : 内核标题或操作系统标识,字符串,可自由修改
root (hd0,0) : 内核文件所在的设备,对grub而言,所有硬盘类型一率为hd,hd#表示第几个磁盘,最后的0表示对应磁盘的分区格式为(hd#,N)常见的主分区0,1,2,3
kernel : 内核文件的路径,及传递给内核的参数(和cat /proc/cmdline内容一样);注意:此路径是指GRUB访问的路径,而不是文件系统访问的路径
kernel /vmlinuz-2.6.32-696.el6.x86_64 表示的是boot单独挂载在一个分区上
kernel /boot/vmlinuz-2.6.32-696.el6.x86_64 表示的是boot和根挂载在同一个分区
initrd : initramfs文件及路径,是一个小的完整意义上的linux,是安装Linux操作系统的最后一步通过动态收集内核为了访问根文件系统所在设备必要的驱动
initrd /initramfs-2.6.32-696.el6.x86_64.img
第三阶段
- 内核Kernel要执行/sbin/init,就必须能够先访问根文件系统,因为在Linux下,文件系统从根/目录开始,就是根文件系统rootfs
- Linux是单内核结构
- 内核本身要尽可能的小,因为内核是常驻内存的,同时内核要尽可能多的支持各种类型的硬件,支持更多的类型硬件意味着内核就会变大,占用更多的内存空间,解决方法:通过模块化的设计.ko来实现内核模块的动态装载和卸载,模块不仅包括驱动程序,也可以包括文件系统,加密功能等
- Linux内核有两部分组成,核心和外围模块。初始化时只是核心本身,外围模块在/lib/modules/“内核版本号命名的目录"/
- Linux内核名称: `uname -r` 2.6.32-696.el6.x86_64 内核文件:vmlinuz-2.6.32-696.el6.x86_64 ,模块所在的目录/lib/modules/2.6.32-696.el6.x86_64,如果是多内核的安装方式,可以在/boot目录下看到多个内核文件vmlinuz_*以及在/lib/modules/下的多个和内核同名称的文件夹
- 在/boot目录下还有一个以initramfs-2.6.32-696.el6.x86_64.img文件,这个文件是在安装完操作系统的过程中通过脚本或命令生成的,动态收集内核为了访问根所在的设备需要的驱动程序,并且生成initramfs-2.6.32-696.el6.x86_64.img文件
- initramfs-2.6.32-696.el6.x86_64.img专业名称:伪根文件系统,起临时过渡的作用,由bootloader装载到内存,把内存模拟成磁盘用(ramfs),因为initramfs-2.6.32-696.el6.x86_64.img文件中已经完全包含了rootfs根文件系统的驱动,所以内核通过initramfs来访问根文件系统,从而找到/sbin/init来启动用户空间的第一个进程可以100%成功
- bootloader能访问的分区,一定是一个基本的磁盘设备,内核Kernel也一定能识别和访问,内核Kernel和initramfs都是由bootloader装载的,所以两个文件必须位于同一个磁盘设备同一分区
第四阶段
- 在CentOS6中,/sbin/init同时读取/etc/inittab和/etc/init/*.conf配置文件
- /sbin/init是用户空间的第一个进程,管理所有用户空间的进程,除非要调用硬件,才会切换到内核空间
- CentOS7此名字是systemd
- 运行系统初始化脚本/etc/rc.d/rc.sysinit
- 运行/etc/rc.d/rc脚本,此脚本作用是根据所选择的运行级别作为位置参数,然后去触发运行rc.{0..6}.d下的以K*和S*开头的脚本,K*表示kill,S*表示start目录/etc/rc.d/init.d下的服务脚本。K*和S*以软链接的方式对应/etc/rc.d/init.d下的服务脚本。
- 运行/etc/rc.d/rc.local脚本,此脚本可以运行用户自开发的初始化脚本
- 执行/bin/login程序,等待用户登录
- 最后一步,登录之后开始以Shell控制主机
Linux启动失败及恢复方法
GRUB stage1失败情形:破坏bootloader所在的分区
破坏方法:
- 备份MBR dd if=/dev/sda of=/data/mbr bs=1 count=512
- 破坏MBR dd if=/dev/zero of=/dev/sda bs=1 count=446
- 检查hexdump -C -n 512 /dev/sda -v
- 重启reboot
启动故障现象:
恢复方法:
- 进入救援模式
- 找到mbr保存的路径 /mnt/sysimage/data
- 恢复 dd if=/mnt/sysimage/data/mbr of=/dev/sda bs=1 count=446
- 也可以通过grub-install /dev/sda来恢复,先通过光盘引导救援模式,执行chroot /mnt/sysimage
- 也可以通过grub命令修复,这种修复方法依赖/boot/grub下的部分文件
-
grub> root (hd0,0) :root (hd0,0) Filesystem type is ext2fs, partition type 0x83
-
grub> setup (hd0) : setup (hd0) Checking if "/boot/grub/stage1" exists... yes Checking if "/boot/grub/stage2" exists... yes Checking if "/boot/grub/e2fs_stage1_5" exists... yes Running "embed /boot/grub/e2fs_stage1_5 (hd0)"... 27 sectors are embedded.succeeded Running "install /boot/grub/stage1 (hd0) (hd0)1+27 p (hd0,0)/boot/grub/stage2 / boot/grub/grub.conf"... succeededDone.
- 重启 reboot
grub命令和grub-install恢复比较:
破坏方法:
- 删除除grub.conf,splash.xpm.gz之外的所有文件
- 破坏MBR dd if=/dev/zero of=/dev/sda bs=1 count=446
恢复方法:
- 尝试通过grub命令恢复失败
- grub> root (hd0,0)root (hd0,0) Filesystem type is ext2fs, partition type 0x83
-
grub> root (hd0,0)
root (hd0,0)
Filesystem type is ext2fs, partition type 0x83
grub> setup (hd0)
setup (hd0)
Checking if "/boot/grub/stage1" exists... no
Checking if "/grub/stage1" exists... noError 15t: File not found
- 此时可以用grub-install /dev/sda可以成功恢复,同时还可以把/etc/grub下的所有文件生成
结论:
- grub命令恢复依赖于/boot/grub的文件
- 对于干净的系统(没有做过恢复的系统),/boot/grub下除grub.conf,splash.xpm.gz之外的文件不是系统启动的必要文件,即删除这些文件不会影响到系统的启动
- 一旦使用grub或grub-install做过恢复,/boot/grub下的文件是系统启动的必要文件,删除会导致系统无法正常启动
如下图就是用grub或grub-install恢复过系统后删除/boot/grub下除grub.conf,aplash.xpm.gz之外所有文件启动后的报错信息
GRUB stage1.5失败情形:破坏bootloader后续27个扇区所在的分区
破坏方法:
- dd if=/dev/zero of=/dev/sda bs=1 count=10000 skip=512 seek=512
启动故障现象:
无法自动从光驱启动,由于512bytes的MBR并没有被破坏,这也符合我们之前的结论:但凡读取了一个设备的MBR,如果MBR中的bootloader损坏,无法正常启动,操作系统不会再去读第二个设备的MBR
恢复方法:
- 修改BIOS的启动抗顺序,从光驱启动进入救援模式
- chroot /mnt/sysimage
- 用grub-install命令修复:
- 重启reboot
GRUB stage2失败情形:破坏/boot/grub/下的grub.conf文件
破坏方法:
- 删除/boot/grub下的所有文件
- 重启系统
启动故障现象:
恢复方法:
- kernel /vmlinuz-2.6.32-696.el6.x86_64 root=/dev/sda2(此处是指根文件系统所有的分区,而不是boot所在的分区)
- initrd /initramfs-2.6.32-696.el6.x86_64.img
- boot
遗留问题:
对于grub.conf配置文件中如下的内核文件的路径仍然是疑惑。希望后续随着知识点的累计能自己解惑。
kernel : 内核文件的路径,及传递给内核的参数(和cat /proc/cmdline内容一样);注意:此路径是指GRUB访问的路径,而不是文件系统访问的路径。
kernel /vmlinuz-2.6.32-696.el6.x86_64 表示boot单独挂载在一个分区上
kernel /boot/vmlinuz-2.6.32-696.el6.x86_64 表示boot和根挂载在同一个分区