Linux 启动过程是初始化系统的过程。 它包括从第一次打开计算机电源到用户界面完全可操作时发生的所有事情。
充分了解引导过程中的步骤可能有助于您解决问题,以及根据您的需要调整计算机的性能。
另一方面,启动过程可能相当技术性,您可以在不了解所有细节的情况下开始使用 Linux。
第一个步骤:BIOS
启动基于 x86 的 Linux 系统涉及许多步骤。 当计算机开机时,基本输入/输出系统 (BIOS) 会初始化硬件,包括屏幕和键盘,并测试主内存。 此过程也称为 POST(开机自检)。
BIOS 软件存储在主板上的 ROM 芯片上。 此后,引导过程的其余部分由操作系统 (OS) 控制。
Master Boot Record (MBR) and Boot Loader
一旦 POST 完成,系统控制就会从 BIOS 传递到引导加载程序。引导加载程序通常存储在系统中的硬盘之一上,或者在引导扇区(对于传统 BIOS/MBR 系统)或 EFI 分区(对于更新的(统一)可扩展固件接口或 EFI/UEFI 系统)。到此阶段为止,机器不会访问任何大容量存储介质。此后,有关日期、时间和最重要外围设备的信息从 CMOS 值中加载(在使用电池供电的内存存储技术后,即使系统断电也能跟踪日期和时间) .
有许多用于 Linux 的引导加载程序;最常见的是 GRUB(用于 GRand Unified Boot loader)、ISOLINUX(用于从可移动媒体启动)和 DAS U-Boot(用于在嵌入式设备/设备上启动)。大多数 Linux 引导加载程序可以提供一个用户界面,用于选择引导 Linux 的替代选项,甚至可能安装的其他操作系统。在引导 Linux 时,引导加载程序负责将内核映像和初始 RAM 磁盘或文件系统(其中包含启动系统所需的一些关键文件和设备驱动程序)加载到内存中。
Boot Loader in Action
引导加载程序有两个不同的阶段:
对于使用 BIOS/MBR 方法的系统,引导加载程序位于硬盘的第一个扇区,也称为主引导记录 (MBR)。 MBR 的大小仅为 512 字节。在此阶段,引导加载程序检查分区表并找到可引导分区。一旦找到可引导分区,它就会搜索第二阶段引导加载程序,例如 GRUB,并将其加载到 RAM(随机存取存储器)中。对于使用 EFI/UEFI 方法的系统,UEFI 固件读取其引导管理器数据以确定要启动哪个 UEFI 应用程序以及从何处启动(即可以从哪个磁盘和分区找到 EFI 分区)。然后,固件启动 UEFI 应用程序,例如 GRUB,如固件启动管理器的启动项中所定义。这个过程更复杂,但比旧的 MBR 方法更通用。
第二阶段引导加载程序位于 /boot 下。将显示启动画面,让我们可以选择要启动的操作系统 (OS)。选择操作系统后,引导加载程序将所选操作系统的内核加载到 RAM 中,并将控制权交给它。内核几乎总是被压缩,所以它的首要任务是解压缩自身。之后,它将检查和分析系统硬件并初始化内核中内置的任何硬件设备驱动程序。
Initial RAM Disk
initramfs 文件系统映像包含执行挂载正确根文件系统所需的所有操作的程序和二进制文件,例如为所需的文件系统和大容量存储控制器的设备驱动程序提供内核功能,使用名为 udev(用于用户设备)的工具,它负责用于确定存在哪些设备,定位它们需要正确运行的设备驱动程序,并加载它们。找到根文件系统后,检查错误并安装。
挂载程序指示操作系统文件系统已准备好使用,并将其与文件系统整个层次结构中的特定点(挂载点)相关联。如果成功,initramfs 将从 RAM 中清除并执行根文件系统 (/sbin/init) 上的 init 程序。
init 处理挂载和转向最终的真实根文件系统。如果在访问大容量存储之前需要特殊的硬件驱动程序,它们必须在 initramfs 映像中。
Text mode logins
在启动过程接近尾声时,init 会启动一些文本模式登录提示。这些使您能够键入您的用户名,然后是您的密码,并最终获得一个命令外壳。但是,如果您正在运行带有图形登录界面的系统,您一开始不会看到这些。
通常,默认的命令 shell 是 bash(GNU Bourne Again Shell),但还有许多其他高级命令 shell 可用。 shell 打印一个文本提示,表明它已准备好接受命令;用户输入命令并回车后,命令被执行,命令执行完成后会显示另一个提示。
正如您将在第 7 章:命令行操作中学到的那样,可以使用 ALT 键和一个功能键来访问运行命令 shell 的终端。大多数发行版以 F1 或 F2 开头,有六个文本终端和一个图形终端。在图形环境中,切换到文本控制台需要按 CTRL-ALT + 相应的功能键(使用 F7 或 F1 通向 GUI)。
Linux Kernel
引导加载程序将内核和基于 RAM 的初始文件系统 (initramfs) 加载到内存中,因此内核可以直接使用它。
当内核加载到 RAM 中时,它会立即初始化和配置计算机的内存,并配置连接到系统的所有硬件。 这包括所有处理器、I/O 子系统、存储设备等。内核还加载一些必要的用户空间应用程序。
/sbin/init and Services
一旦内核设置了所有硬件并挂载了根文件系统,内核就会运行 /sbin/init。然后这成为初始进程,然后启动其他进程以使系统运行。系统上的大多数其他进程最终都会追溯到 init;例外包括所谓的内核进程。它们由内核直接启动,它们的工作是管理内部操作系统的详细信息。
除了启动系统之外,init 还负责保持系统运行和干净地关闭系统。它的职责之一是在必要时作为所有非内核进程的管理者;完成后进行清理,并在用户登录和退出时根据需要重新启动用户登录服务,其他后台系统服务也是如此。
传统上,此进程启动是使用可追溯到 1980 年代的约定和 System V UNIX 版本完成的。这个串行进程让系统通过一系列运行级别,其中包含启动和停止服务的脚本集合。每个运行级别都支持不同的系统运行模式。在每个运行级别内,可以将单个服务设置为运行,或者在运行时关闭。
然而,最近的所有主要发行版都不再采用这种系统初始化的顺序运行级别方法,尽管它们通常出于兼容性目的支持 System V 约定。接下来,我们将讨论较新的方法 systemd 和 Upstart。
Startup Alternatives
SysVinit 将事物视为一个连续的过程,分为一系列连续的阶段。每个阶段都需要完成才能进行下一个阶段。因此,启动不容易利用可以在多个处理器或内核上完成的并行处理。
此外,关机和重启被视为一种相对罕见的事件;究竟花了多长时间并不重要。这不再是事实,尤其是对于移动设备和嵌入式 Linux 系统。一些现代方法,例如使用容器,可能需要几乎瞬时的启动时间。因此,系统现在需要具有更快和增强功能的方法。最后,旧的方法需要相当复杂的启动脚本,这些脚本很难在发行版本、内核版本、体系结构和系统类型之间保持通用。开发的两个主要替代方案是:
Updtart
-
- 由 Ubuntu 开发并于 2006 年首次收录
- 在 Fedora 9(2008 年)和 RHEL 6 及其克隆中采用。
systemd
-
- Fedora 首先采用(2011 年)
- 被 RHEL 7 和 SUSE 采用
- 在 Ubuntu 16.04 中替换了 Upstart
虽然迁移到 systemd 颇有争议,但它已被主要发行版采用,因此我们不会讨论旧的 System V 方法或 Upstart,后者已成为死胡同。不管人们对 systemd 的争议或技术方法有何看法,几乎普遍采用使学习如何在 Linux 系统上工作变得更简单,因为发行版之间的差异较小。我们接下来列举 systemd 的特性。
systemd Features
使用 systemd 的系统比使用早期 init 方法的系统启动得更快。这主要是因为它用激进的并行化技术替换了一组串行化的步骤,允许同时启动多个服务。
复杂的启动shell脚本被更简单的配置文件所取代,这些配置文件列举了服务启动前必须做的事情,如何执行服务启动,以及服务在启动完成时应该表明什么条件已经完成。需要注意的一件事是 /sbin/init 现在只指向 /lib/systemd/systemd;即 systemd 接管 init 进程。
一个 systemd 命令 (systemctl) 用于大多数基本任务。虽然我们还没有讨论在命令行上工作,但这里是其用法的简要列表:
- 在当前运行的系统上启动、停止、重启服务(以 nfs 为例):
$ sudo systemctl start|stop|restart nfs.service
- 启用或禁用系统服务在系统引导时启动:
$ sudo systemctl enable|disable nfs.service
在大多数情况下,可以省略 .service。与旧方法存在许多技术差异,超出了我们的讨论范围。
更多Jerry的原创文章,尽在:“汪子熙”: