Linux 启动与 BIOS/UEFI、GRUB2 核心知识点梳理

Linux 启动与 BIOS/UEFI、GRUB2 核心知识点梳理

一、BIOS与UEFI

BIOS 与 UEFI 核心对比

二者均为计算机开机时首先运行的系统固件,UEFI 是 BIOS 的新一代替代方案,核心差异和 UEFI 优势如下:

特性 BIOS UEFI
硬盘支持 支持MBR 格式,最大 2TB,仅 4 个主分区 GPT 格式,最大 18EB,Win 下支持 128 个分区,无主 / 逻辑分区概念
操作界面 纯字符,仅键盘操作 图形界面,原生分辨率,支持鼠标
容错与扩展 无模块化,扩展性差 模块化构建,容错强;开放可编程接口,支持厂商扩展(备份 / 诊断)
网络支持 开机未进系统即可联网,支持远程故障诊断
开发 / 标准化 1975 年推出,老旧标准 1998 年 Intel 开发(原 EFI),2005 年标准化为 UEFI

二、Linux启动流程

现代计算机是软件与硬件的复杂组合,从接通电源开始,到可以登录到系统中,需要大量的软件和硬件的配合,我们一起来了解一下CentOS8的x86_64系统在启动过程中所涉及的任务,虚拟机的流程也是大致相同的,但是某些与硬件相关的步骤是由虚拟机的相关程序在软件中处理的。

图片

从通电到进入登录界面,硬件 + 固件 + 系统程序的协同流程,虚拟机仅硬件相关步骤由软件模拟,其余一致:

  1. 通电自检

    :固件(BIOS/UEFI)初始化,执行 POST 开机自检,初始化基础硬件

  2. 查找启动设备

    :BIOS 按配置顺序查 MBR;UEFI 按固件配置直接识别启动设备

  3. 加载启动加载器

    :固件从启动设备读取GRUB2(CentOS8 默认 boot loader)并移交控制权

  4. 加载 GRUB2 配置

    :GRUB2 读取/boot/grub2/grub.cfg,显示内核选择菜单(可通过grub2-mkconfig生成该文件)

  5. 加载内核与 initramfs

    :选择内核 / 超时后,加载vmlinuz(内核)和initramfs(临时根文件系统,含硬件驱动 + 初始化脚本)

  6. 移交控制权给内核

    :GRUB2 完成加载,将系统控制权交给内核

  7. 内核初始化

    :内核通过 initramfs 加载硬件驱动,启动/usr/sbin/init(PID=1,CentOS8 中为systemd的软链接)

  8. 启动 initrd.target 并挂载根

    :systemd 执行initrd.target所有单元,按/etc/fstab将真实根文件系统挂载到/sysroot/

  9. 切换根文件系统

    :从临时的 initramfs 切换到/sysroot(硬盘上的真实根),重新执行磁盘上的 systemd

  10. 启动默认目标

    :systemd 启动内核命令行 / 系统配置的默认目标,进入对应登录界面(字符 / 图形)

三、运行级别切换与相关配置文件

运行级别切换

通过前面的课程我们了解到CentOS8在启动过程中需要判断对应的运行级别,在不同的运行级别中会启动不同的单元,那么运行级别如何切换呢?

在CentOS8中运行级别的设置涉及到下面几个命令

1
2
3
4
systemctl isolate.../init [0-6]切换运行级别
systemctlget-default查看当前的默认运行级别
systemctl set-default ...设置默认的运行级别
runlevel查看之前的运行级别和当前的运行级别

运行级别对照

1
2
3
4
5
6
7
8
9
[root@localhost system]# cd /usr/lib/systemd/system
[root@localhost system]# ll runlevel*.target
runlevel0.target -> poweroff.target
runlevel1.target -> rescue.target
runlevel2.target -> multi-user.target
runlevel3.target -> multi-user.target
runlevel4.target -> multi-user.target
runlevel5.target -> graphical.target
runlevel6.target -> reboot.target

所以当我们使用init [0-6]切换运行级别的时候系统执行的是systemctl isolate runlevel[0-6].target

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost ~]# runlevel #查看运行级别
N 5
[root@localhost ~]# init 3#切换到字符界面
[root@localhost ~]# runlevel #查看运行级别
5 3
[root@localhost ~]# systemctl isolate graphical.target #切换到图形界面
[root@localhost ~]# runlevel
3 5

#########
emergency.target
[root@localhost ~]# systemctl isolate emergency.target
注意:此为紧急模式,用于紧急处理系统的错误,无法使用rescue.target时,可以尝试使用此模式。

四、Boot Loader与GRUB2

前面我们了解的CentOS8的启动流程,在这个流程中有一个叫启动加载器,也就是boot loader的工具,如果没有这个boot loader就无法加载内核。在CentOS8中使用的是启动加载器是Grub2,在了解Grub2之前,我们先聊一下boot loader

4.1、Boot Loader的两个阶段

我们知道在BIOS或者UEFI加载完成之后,会到MBR中读取boot loader,这个boot loader可以让用户选择加载的内核并且移交系统的控制权限等,而加载内核只能通过boot loader,但是boot loader在MBR中,这个MBR是硬盘的第一个扇区,一个扇区的大小是512字节,boot loader的大小只有446字节,即便是GPT磁盘也没有足够的空间存储boot loader所包含的内容,所以为了避免空间的限制,导致无法引导系统正常启动的问题,Linux将boot loader的工作过程分为了两步。

stage1 执行boot loader的主程序主程序必须安装在MBR或者是启动扇区,由于空间限制,MBR或启动扇区仅存放最小化的boot loader,并不会存放相关的配置文件

stage2 通过主程序加载配置文件通过boot loader的主程序加载所有相关的配置文件,这些配置文件中包括定义文件系统类型的和CentOS8中的grub.cfg文件,而这些文件通常都存放在/boot当中

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost ~]# ll -F /boot/grub2/
总用量 32
-rw-r--r--. 1 root root 64 12月 13 21:50 device.map
drwxr-xr-x. 2 root root 4096 12月 13 21:50 fonts/
-rw-r--r--. 1 root root 5032 12月 13 21:50 grub.cfg
-rw-r--r--. 1 root root 1024 12月 13 21:50 grubenv
drwxr-xr-x. 2 root root 12288 12月 13 21:50 i386-pc/

device.map设备对应文件,用来帮助系统判断磁盘与设备文件的对应关系
fonts开机过程中用到的字体文件
grub.cfggrub2的主配置文件
grubenvgrub环境区块文件大小为1K,用来记录GRUB环境变量
i386-PC针对x86架构的电脑所需要的相关模块,包括电源管理支持,文件系统支持等模块

在这些文件中最重要的就是grub.cfg文件,以及文件系统支持的相关模块

4.2、GRUB2

GRUB与LILO目前为止,linux下的启动加载器有两种,一种是LILO另外一种就是GRUB,由于GRUB的功能更强大,支持的文件系统较多,所以越来越多的操作系统使用GRUB做为boot loader,CentOS从7开始使用了功能更为强大的GRUB2

GRUB2的优点

  • 支持更多的文件系统
  • 开机时可以手动调整启动参数
  • 动态更新配置文件,修改完配置文件后不需要重新安装

GRUB2与硬盘

由于grub2的主要任务是从硬盘当中加载内核,所以grub2必须要识别硬盘,但是grub2识别硬盘的方式与linux系统识别的方式还是有些区别的。在Linux系统中,硬盘一般会被识别为类似sda1这种形式,而在grub2中硬盘会统一被识别为hd的设备,排序方式全部是用数字进行排序,而不是用字母加数字的混合形式。这么做的目的是为了定义grub2的查找内核时的顺序。如:

1
2
3
4
hd0,1搜索第一块硬盘的第一个分区
hd0,msdos1搜索第一块MBR硬盘的第一个分区
hd0,gpt1搜索第一块GPT磁盘的第一个分区
简单来说,两个数字,第一个数字表示硬盘序号,第二个数字表示分区序号

grub2配置文件

了解了grub2中的硬盘识别方式,我们就可以了解一下grub2的配置文件了,这个文件建议各位不要随意更改

1
2
3
4
5
6
7
8
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub2-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

此部分内容提示我们不要编辑这个文件,此文件是有grub2-mkconfig命令自动建立的,相关模板与设置存放在/etc/grub.d/目录以及/etc/default/grub中,也就是说grub.cfg文件的内容会调用/etc/grub.d目录下的内容,如果需要修改的话需要调整/etc/default/grub文件

基本上grub2不希望用户去修改grub.cfg这个文件,如果需要调整的话需要通过修改其它文件并配合grub2-mkconfig命令来生成新的grub.cfg文件,但是各位还是要了解一下这个文件的大致格式

/etc/default/grub与/etc/grub.d/

在前面我们知道了grub2的配置文件是grub.cfg,但是此文件内容比较复杂,且官方不建议我们手动修改,如果需要修改的话需要通过/etc/default/grub文件以及/etc/grub.d/目录内的内容来实现,那我们一起来看一下

/etc/default/grub

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# vim /etc/default/grub
GRUB_TIMEOUT=5定义在启动菜单默认的等待时间,单位是秒
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"定义获取操作系统名称的方式
GRUB_DEFAULT=saved定义开机时默认启动的项目,可以是数字,也可以是标题名称,(这个标题就是开机时看到的那个标题),还可以是saved(表示默认启动上次启动成功的操作系统)
GRUB_DISABLE_SUBMENU=true是否隐藏子菜单
GRUB_TERMINAL_OUTPUT="console"定义启动时的界面使用哪种终端输出,值包含console,serial,gfxterm,vga_text等
GRUB_CMDLINE_LINUX="resume=/dev/mapper/cl-swap rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet"定义额外的启动参数
GRUB_DISABLE_RECOVERY="true"是否启用修复模式
GRUB_ENABLE_BLSCFG=true是否启用bootloader规范

修改完成之后需要使用
grub2-mkconfig -o /boot/grub2/grub.cfg,重新生成配置文件

/etc/grub.d/

00_header 设置默认参数

00_tuned 额外调整的值

01_menu_auto_hide 与菜单隐藏相关的设置

01_users 与用户相关的设置

10_linux 与内核相关的设置

20_ppc_terminfo 与终端相关的设置

20_linux_xen 与虚拟化相关的设置

30_os-prober 与操作系统检测相关

30_uefi-firmware 与UEFI启动设置相关,需要硬件支持

40_custom&41_custom 自定义设置

注:这些文件会按照数字的顺序由小到大加载