共计 7056 个字符,预计需要花费 18 分钟才能阅读完成。
一、BIOS 与 UEFI
BIOS
Basic Input Output System 的缩写,翻译过来就是“基本输入输出系统”,是一种业界标准的固件接口,第一次出现在 1975 年,是计算机启动时加载的第一个程序,主要功能是检测和设置计算机硬件,引导系统启动。
UEFI
Unified Extensible Firmware interface 的缩写,翻译过来为统一可扩展固件接口,是 BIOS 的替代方案,前身是 Intel 在 1998 年开始开发的 Inter Bot Initiative,后来被命名为可扩展固件接口(Extensible Firmware Interface EFI),2005 年交由统一可扩展固件接口论坛,并更名为 UEFI
UEFI 的优势
1、支持硬盘容量更大:相比于传统 BIOS+MBR 只能支持 2048G 的硬盘分区和 4 个主分区相比,UEFI+GPT 不会受到硬盘容量大小、分区数量的限制,不过在 Windows 系统上由于系统的限制,支持最多 128 个 GPT 磁盘分区,最大分区 18EB,并且 GPT 格式是没有主分区和逻辑分区这个概念的
2、容错特性:UEFI 是模块化构建,比 BIOS 容错和纠错特性强。
3、鼠标操作:UEFI 内置图形驱动,可以提供原生分辨率的图形环境,用户进入后可以使用鼠标调整。
4、扩展性强:UEFI 包含一个可编程的开放接口,厂商利用这个接口可以对功能进行扩展,如:备份和诊断
5、支持联网:在不进入操作系统的前提下就可以通过网络进行远程故障诊断
二、CentOS8 启动流程
现代计算机是软件与硬件的复杂组合,从接通电源开始,到可以登录到系统中,需要大量的软件和硬件的配合,我们一起来了解一下 CentOS8 的 x86_64 系统在启动过程中所涉及的任务,虚拟机的流程也是大致相同的,但是某些与硬件相关的步骤是由虚拟机的相关程序在软件中处理的。
1、接通电源
系统固件(UEFI 或 BIOS 初始化)运行开机自检,并初始化部分硬件
2、系统固件搜索可启动设备
启动设备可能是 UEFI 启动固件中配置的,也可能是按照 BIOS 中配置的顺序搜索所有磁盘上的主启动记录(MBR)
3、读取启动加载器(boot loader)
系统固件会从 MBR 中读取启动加载器,然后将控制权交给启动加载器,在 CentOS8 中启动加载器为 GRUB2
4、grub.cfg
GRUB2 将从 /boot/grub2/grub.cfg 文件中加载配置并显示一个菜单,在这个菜单中可以选择要启动的内核,我们可以使用 grub2-mkconfig 命令配合 /etc/grub.d/ 目录和 /etc/default/grub 文件生成 grub.cfg 文件。
[root@zutuanxue ~]# cd /boot/grub2/
[root@zutuanxue grub2]# ls
device.map fonts grub.cfg grubenv i386-pc
[root@zutuanxue grub2]# pwd
/boot/grub2
5、initramfs
在选择内核或到达超时时间后,启动加载器会从磁盘加载内核 (vmlinuz) 和 initramfs,并将它们放入内存中,initramfs 中包含启动时所有必要硬件的内核模块(驱动)和初始化脚本等,使用 lsinitrd 和 dracut 命令配合 /etc/dracut.conf.d/ 目录可以查看和配置 initramfs 文件
[root@zutuanxue grub2]# lsinitrd | more
Image: /boot/initramfs-4.18.0-80.el8.x86_64.img: 27M
## 可以在回显中看到系统的主要目录,包括 /etc /usr /dev /lib /lib64 等
6、启动加载器放权
启动加载器将控制权交给内核
7、内核初始化
内核会在 initramfs 中寻找硬件的相关驱动并初始化相关硬件,然后启动 /usr/sbin/init(PID=1),在 CentOS8 中 /sbin/init 是 systemd 的链接
[root@zutuanxue grub2]# ll /sbin/init
lrwxrwxrwx. 1 root root 22 5月 23 2019 /sbin/init -> ../lib/systemd/systemd
[root@zutuanxue grub2]# find / -name systemd
/usr/lib/systemd/systemd
8、启动 initrd.target 并挂载
systemd 会执行 initrd.target 包含的所有单元,并将根文件系统挂载到 /sysroot/ 目录, 在 initrd.target 启动时的依赖单元,会按照 /etc/fstab 设置对硬盘进行挂载
9、切换根文件系统
内核将根文件系统从 initramfs 切换为 /sysroot(硬盘上的根文件系统),systemd 会找到磁盘上安装的 systemd 并自动重新执行
10、启动相应目标
硬盘上安装的 systemd 会查找从内核命令行传递的目标或是系统中配置的默认目标并启动对应单元后就可以进入到对应的登录界面。默认目标是 /etc/systemd/system/default.target,
注意:
字符界面:
如果默认目标为 multi-user.target(字符界面),systemd 会先执行 sysinit.target 初始化系统之后执行 basic.target 与 getty.target 准备基本系统环境和终端,再启动 multi-user.target 下的相关应用,同时执行 /etc/rc.d/rc.local(需要执行权限)与与登录服务(systemd-logind.service),开启登录界面
[root@zutuanxue ~]# systemctl list-dependencies multi-user.target | grep target
multi-user.target
● ├─basic.target
● │ ├─paths.target
● │ ├─slices.target
● │ ├─sockets.target
● │ ├─sysinit.target
● │ │ ├─cryptsetup.target
● │ │ ├─local-fs.target
● │ │ └─swap.target
● │ └─timers.target
● ├─getty.target
● ├─nfs-client.target
● │ └─remote-fs-pre.target
● └─remote-fs.target
● └─nfs-client.target
● └─remote-fs-pre.target
图形界面:
在 multi-user.target 的基础上执行 graphical.target 启动所需要的服务,开启图形界面
[root@zutuanxue ~]# systemctl list-dependencies graphical.target | grep target
graphical.target
● └─multi-user.target
● ├─basic.target
● │ ├─paths.target
● │ ├─slices.target
● │ ├─sockets.target
● │ ├─sysinit.target
● │ │ ├─cryptsetup.target
● │ │ ├─local-fs.target
● │ │ └─swap.target
● │ └─timers.target
● ├─getty.target
● ├─nfs-client.target
● │ └─remote-fs-pre.target
● └─remote-fs.target
● └─nfs-client.target
● └─remote-fs-pre.target
三、运行级别切换与相关配置文件
运行级别切换
通过前面的课程我们了解到 CentOS8 在启动过程中需要判断对应的运行级别,在不同的运行级别中会启动不同的单元,那么运行级别如何切换呢?
在 CentOS8 中运行级别的设置涉及到下面几个命令
systemctl isolate .../init [0-6] 切换运行级别
systemctl get-default 查看当前的默认运行级别
systemctl set-default ... 设置默认的运行级别
runlevel 查看之前的运行级别和当前的运行级别
运行级别对照
[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
[root@zutuanxue ~]# runlevel #查看运行级别
N 5
[root@zutuanxue ~]# init 3 #切换到字符界面
[root@zutuanxue ~]# runlevel #查看运行级别
5 3
[root@zutuanxue ~]# systemctl isolate graphical.target #切换到图形界面
[root@zutuanxue ~]# runlevel
3 5
#########
emergency.target
[root@zutuanxue ~]# 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 当中
[root@zutuanxue ~]# 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.cfg grub2 的主配置文件
grubenv grub 环境区块文件大小为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 的查找内核时的顺序。如:
hd0,1 搜索第一块硬盘的第一个分区
hd0,msdos1 搜索第一块 MBR 硬盘的第一个分区
hd0,gpt1 搜索第一块 GPT 磁盘的第一个分区
简单来说,两个数字,第一个数字表示硬盘序号,第二个数字表示分区序号
grub2 配置文件
了解了 grub2 中的硬盘识别方式,我们就可以了解一下 grub2 的配置文件了,这个文件建议各位不要随意更改
#
# 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**
[root@zutuanxue ~]# 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 自定义设置
注:这些文件会按照数字的顺序由小到大加载