10 引导过程简介 #
引导 Linux 系统涉及不同组件和任务。固件和硬件初始化过程(取决于计算机的体系结构)完成后,系统将通过引导加载程序 GRUB 2 启动内核。在此之后,引导进程完全由操作系统控制,并由 systemd
处理。systemd
会提供一组“目标”,用于引导与日常使用、维护或紧急情况相关的配置。
10.1 术语 #
本章使用的术语可能存在歧义。为了理解本章中术语的用法,请阅读以下定义:
init
有两个不同的进程通常命名为 “init”:
用于装入根文件系统的
initramfs
进程从实际根文件系统执行且用于启动其他所有进程的操作系统进程
在这两种情况下,
systemd
程序都会处理此任务。首先会从initramfs
执行此进程,以装入根文件系统。装入成功后,将从根文件系统以初始进程的形式重新执行此进程。为了避免混淆这两个systemd
进程,我们将第一个进程称为 init on initramfs,将第二个进程称为 systemd。-
initrd
/initramfs
initrd
(初始 RAM 磁盘)是一个映像文件,内含内核所装载的并且作为临时根文件系统从/dev/ram
装入的根文件系统映像。装入此文件系统需要使用文件系统驱动程序。从内核 2.6.13 开始,initrd 已由
initramfs
(初始 RAM 文件系统)取代,后者无需文件系统驱动程序即可装入。SUSE Linux Enterprise Server 只使用initramfs
。但是,由于initramfs
作为/boot/initrd
储存,因此通常将其称为“initrd”。本章只使用名称initramfs
。
10.2 Linux 引导进程 #
Linux 引导进程包括多个阶段,每个阶段由一个不同组件来代表:
10.2.1 初始化和引导加载程序阶段 #
在初始化阶段,将设置计算机的硬件并准备好设备。此过程根据硬件体系结构的不同有很大的差别。
SUSE Linux Enterprise Server 在所有体系结构中都使用引导加载程序 GRUB 2。根据体系结构和固件,启动 GRUB 2 引导加载程序的过程可能包括多个步骤。引导加载程序的用途是装载内核以及基于 RAM 的初始文件系统 (initramfs)。有关 GRUB 2 的详细信息,请参见第 12 章 “引导加载程序 GRUB 2”。
10.2.1.1 AArch64 及 Intel 64/AMD64 上的初始化和引导加载程序阶段 #
在打开计算机之后,BIOS 或 UEFI 将初始化屏幕和键盘并测试主内存。直到这一阶段,计算机不访问任何大容量储存媒体。随后,将从 CMOS 值装载有关当前日期、时间和最重要的外设的信息。识别引导媒体及其几何尺寸之后,系统控制权将从 BIOS/UEFI 转到引导加载程序。
在装配传统 BIOS 的计算机上,只能装载引导磁盘的第一个 512 字节物理数据扇区(主引导记录,MBR)中的代码。只有极少量的 GRUB 2 代码能够装入 MBR。引导加载程序的唯一作用就是从 MBR 与第一个分区(MBR 分区表)之间的间隙处,或是从 BIOS 引导分区(GPT 分区表)装载包含文件系统驱动程序的 GRUB 2 核心映像。此映像包含文件系统驱动程序,因此能够访问根文件系统中的 /boot
。/boot
包含 GRUB 2 核心的附加模块以及内核和 initramfs 映像。获取此分区的访问权限后,GRUB 2 会将内核和 initramfs 映像装载到内存中,并将控制权交接到内核。
从包含已加密分区 /boot
的加密文件系统引导 BIOS 系统时,需要输入解密口令两次。GRUB 2 使用第一次输入的口令来解密 /boot
,systemd
使用第二次输入的口令来装载加密的卷。
在装配 UEFI 的计算机上,引导过程比装配传统 BIOS 的计算机要简单得多。固件能够读取包含 GPT 分区表的磁盘的 FAT 格式化系统分区。此 EFI 系统分区(在运行的系统中装载为 /boot/efi
)可提供足够的空间用于托管由固件直接装载和执行的完备 GRUB 2。
如果 BIOS/UEFI 支持网络引导,则也可以配置提供引导加载程序的引导服务器。然后,可以通过 PXE 引导系统。BIOS/UEFI 充当引导加载程序。它会从引导服务器获取引导映像,然后启动系统。这完全不依赖本地硬盘。
10.2.1.2 IBM Z 上的初始化和引导加载程序阶段 #
在 IBM Z 上,必须通过名为 zipl
(z initial program load,z 初始程序装载)的引导加载程序来初始化引导过程。尽管 zipl
支持读取不同的文件系统,但它不支持 SLE 默认文件系统 (Btrfs) 或者从快照引导。因此,SUSE Linux Enterprise Server 使用两阶段的引导过程来确保在引导时提供完整的 Btrfs 支持:
zipl
从 ext2 格式化分区/boot/zipl
引导。此分区包含一个极简的内核,以及一个装载到内存中的 initramfs。initramfs 包含 Btrfs 驱动程序(及其他组件)和引导加载程序 GRUB 2。内核是使用参数initgrub
(告知要启动 GRUB 2)启动的。内核会装入根文件系统,使
/boot
可访问。现在,将从 initramfs 启动 GRUB 2。GRUB 2 从/boot/grub2/grub.cfg
读取其配置,并从/boot
装载最终的内核和 initramfs。现在,将通过 Kexec 装载新内核。
10.2.2 内核阶段 #
引导加载程序转交系统控制权后,所有体系结构中的引导过程都是相同的。引导加载程序会将内核和基于 RAM 的初始文件系统 (initramfs
) 都装载到内存中,而内核将接管控制权。
内核设立内存管理并检测 CPU 类型及其功能后,将初始化硬件,并从内存中装入使用 initramfs
装载的临时根文件系统。
10.2.2.1 initramfs
文件 #
initramfs
(初始 RAM 文件系统)是一个小型 cpio 存档,可由内核装载到 RAM 磁盘中。该文件位于 /boot/initrd
中。可以使用名为 dracut
的工具创建该文件,有关细节,请参见 man 8 dracut
。
initramfs
提供了一个极简的 Linux 环境,可用于在装入实际根文件系统之前执行程序。这个最小的 Linux 环境由 BIOS 或 UEFI 例程载入内存,而且除了需要足够的内存外没有特定的硬件要求。initramfs
存档必须始终提供一个名为 init
的可执行文件,该文件执行根文件系统上的 systemd
守护程序,使引导进程得以继续。
在能够装入 root 文件系统并启动操作系统之前,内核需要相应的驱动程序来访问 root 文件系统所在的设备。 这些驱动程序可能包括用于特定类型硬盘的特殊驱动程序,甚至还可能包括访问网络文件系统所需的网络驱动程序。根文件系统所需的模块由 init
on initramfs
装载。装载模块后,udev
将为 initramfs
提供所需的设备。在引导过程的后面,更改 root 文件系统之后需要重新生成设备。可以使用 systemd
单元 systemd-udev-trigger.service
来实现此目的。
10.2.2.1.1 重新生成 initramfs #
由于 initramfs
包含多个驱动程序,因此,每当其中某个驱动程序有新版本发布时,都需要更新 initramfs。在安装包含驱动程序更新的包时可以自动完成这种更新。YaST 或 zypper 通过显示用于生成 initramfs
的命令的输出来告知此状况。但在某些情况下,您需要手动重新生成 initramfs
:
- 由于更换硬件而需添加驱动程序
如果需要更换硬件(例如硬盘),并且引导时此硬件需要内核中的不同驱动程序,则您必须更新
initramfs
文件。打开或创建
/etc/dracut.conf.d/10-DRIVER.conf
并添加以下行(请注意前导空格):force_drivers+=" DRIVER1"
用驱动程序的模块名称替换 DRIVER1。如果您需要添加多个驱动程序,请将其全部列出并以空格分隔:
force_drivers+=" DRIVER1 DRIVER2"
- 将系统目录移到 RAID 或 LVM
每当您要将正在运行的系统中的交换文件或系统目录(例如
/usr
)移到 RAID 或逻辑卷时,都需要创建一个包含软件 RAID 或 LVM 驱动程序支持的initramfs
。为此,请在
/etc/fstab
中创建相关的项,并装入新项(例如,使用mount -a
和/或swapon -a
)。- 将磁盘添加到包含根文件系统的 LVM 组或 Btrfs RAID
每当您要在包含根文件系统的逻辑卷组或者 Btrfs RAID 中添加(或去除)磁盘时,都需要创建一个支持扩容的卷的
initramfs
。请按照过程 10.1 “生成 initramfs”中的指导操作。- 更改内核变量
如果您在
sysctl
界面中通过编辑相关文件(/etc/sysctl.conf
或/etc/sysctl.d/*.conf
)更改了内核变量的值,系统下次重引导时,这项更改将会丢失。即使您在运行时使用sysctl --system
装载这些值,更改也不会保存到 initramfs 文件中。您需要根据过程 10.1 “生成 initramfs”中所述更新该文件。
请注意,以下过程中的所有命令都需要以 root
用户身份执行。
运行以下命令生成新的
initramfs
文件dracut MY_INITRAMFS
请将 MY_INITRAMFS 替换为所选的文件名。新的
initramfs
将创建为/boot/MY_INITRAMFS
。或者运行
dracut -f
。这会重写当前使用的现有文件。(如果在上一步中运行了
dracut -f
,请跳过此步骤。)为上一步中创建的initramfs
文件创建链接:(cd /boot && ln -sf MY_INITRAMFS initrd)
在 IBM Z 体系结构中,还需额外运行
grub2-install
。
10.2.3 init on initramfs 阶段 #
内核从 initramfs
装入的临时根文件系统包含可执行文件 systemd
(下文称为 init
on initramfs
,另请参见第 10.1 节 “术语”)。此程序执行装入正确根文件系统所需的全部操作。它为所需的文件系统提供内核功能,并为使用 udev
的大量储存控制器提供设备驱动程序。
initramfs
上的 init
的主要用途是准备真实 root 文件系统的装入和访问。根据您的系统配置的不同,initramfs
上的 init
负责以下任务。
- 装载内核模块
根据硬件配置的不同,可能需要一些特殊的驱动程序来访问计算机的硬件组件(最重要的组件是硬盘)。要访问最终的 root 文件系统,内核需要装载适当的文件系统驱动程序。
- 提供块特殊文件
内核根据装载的模块生成设备事件。
udev
会处理这些事件并在 RAM 文件系统的/dev
中生成所需的特殊块文件。没有这些特殊文件,文件系统和其他设备将不可访问。- 管理 RAID 和 LVM 设置
如果将系统配置为在 RAID 或 LVM 下保存根文件文件系统,则
initramfs
上的init
将设置 LVM 或 RAID 以支持以后对根文件系统的访问。- 管理网络配置
如果将系统配置为使用通过网络装入的 root 文件系统(通过 NFS 装入),则
init
必须确保装载了正确的网络驱动程序,并确保将其设置为支持访问 root 文件系统。如果文件系统驻留在一个联网的块设备(如 iSCSI 或 SAN)上,则与储存服务器的连接也由
initramfs
上的init
设置。SUSE Linux Enterprise Server 支持在主要目标不可用的情况下从次要 iSCSI 目标引导。有关 iSCSI 引导目标配置的更多细节,请参见第 14.3.1 节 “使用 YaST 执行 iSCSI 发起端配置”。
如果根文件系统无法从引导环境中装入,则必须先对其进行检查和修复,才能继续引导。如果文件系统为 Ext3 和 Ext4,文件系统检查程序将会自动启动。如果是 XFS 和 Btrfs 文件系统,则不会自动开始修复过程,而是向用户显示有关可用于修复文件系统的选项的信息。成功修复文件系统后,退出引导环境将会使系统重试装入根文件系统。如果装入成功,将正常继续引导。
10.2.3.1 安装过程中的 init on initramfs 阶段 #
如果在安装过程的初始引导阶段调用 init
on initramfs
,它要执行的任务将与上述任务不同。请注意,安装系统不会从 initramfs
启动 systemd
,这些任务由 linuxrc
执行。
- 查找安装媒体
当您启动安装进程时,计算机会装载一个安装内核以及一个包含 YaST 安装程序的特殊
init
。YaST 安装程序正在 RAM 文件系统中运行,它需要知道安装媒体的位置,才能访问安装媒体以安装操作系统。- 启动硬件识别并装载适当的内核模块
如第 10.2.2.1 节 “
initramfs
文件”中所述,引导过程从最少的一组驱动程序(可在大多数硬件配置中使用)开始。在 AArch、POWER 和 Intel 64/AMD64 计算机上,linuxrc
会启动初始硬件扫描过程,以确定适合您的硬件配置的驱动程序集。在 IBM Z 上,需要提供驱动程序列表及其参数,例如,通过 linuxrc 或 parmfile 提供。这些驱动程序用于生成引导系统所需的自定义
initramfs
。如果引导时不需要这些模块,但冷插拔时需要,您可以使用systemd
装载这些模块。有关详细信息,请参见第 13.6.4 节 “装载内核模块”。- 装载安装系统
系统在正确识别硬件后会装载相应的驱动程序。
udev
程序会创建特殊的设备文件,linuxrc
使用 YaST 安装程序启动安装系统。- 启动 YaST
最后,
linuxrc
启动 YaST,后者则启动包安装和系统配置。
10.2.4 systemd 阶段 #
找到“实际的”根文件系统后,对其进行错误检查并装入。如果装入成功,系统会清理 initramfs
并执行根文件系统上的 systemd
守护程序。systemd
是 Linux 的系统和服务管理器。它是作为 PID 1 启动的父进程,充当用于启动和维护用户空间服务的 init 系统。有关详细信息,请参见第 13 章 “systemd
守护程序”。