15.2.FreeBSD 的引导过程
打开计算机并引导操作系统这个过程本身就提出了有趣的难题。根据定义,在操作系统引导之前,计算机本身什么也不会做,包括无法从磁盘运行程序。如果计算机在没有操作系统的情况下无法从磁盘运行程序,而操作系统的程序又正好存放在磁盘上,那操作系统究竟是如何引导的呢?
这个问题类似于《吹牛大王历险记》中的一个情节:主人公掉进下水道,到一半深度时,却靠拉起自己靴子上的提带爬了出来。在计算机发展的早期,“bootstrap”(拔鞋带)这个词就是用来形容引导操作系统的机制的。这个词后来缩写为“booting”(引导)。
在 x86 硬件上,基本输入输出系统(BIOS)负责加载操作系统。BIOS 会在硬盘上查找主引导记录(MBR),该记录必须位于磁盘上的特定位置。BIOS 能加载并运行 MBR,并假设 MBR 能继续执行加载操作系统的其余任务,可能还会借助 BIOS 的帮助。
注意
FreeBSD 支持从旧的 MBR 标准和较新的全局唯一标识分区表(GPT)引导。GPT 分区方式通常用于带有统一可扩展固件接口(UEFI)的计算机。不过,即使是在仅有传统 BIOS 的机器上,FreeBSD 也可使用 gptboot(8) 从 GPT 分区引导。目前正在开发直接从 UEFI 引导的支持。
MBR 中的代码通常称为 引导管理器(boot manager),尤其是当它与用户交互时。引导管理器通常包含磁盘第一磁道或文件系统中的更多代码。引导管理器的例子包括 FreeBSD 的标准 boot manager —— boot0(也叫 Boot Easy),以及许多 Linux® 发行版使用的 GNU GRUB。
注意
使用 GRUB 的用户请参考 GNU 提供的文档。
如果只安装了一个操作系统,MBR 会寻找磁盘上第一个可引导(active)分区,并运行该分区上的代码来加载操作系统的其余部分。当存在多个操作系统时,可安装不同的引导管理器,用来显示操作系统列表,让用户选择要引导的系统。
FreeBSD 的其余引导系统分为三个阶段。第一阶段仅知道如何将计算机引导到特定状态并运行第二阶段。第二阶段可执行更多的操作,然后运行第三阶段。第三阶段完成加载操作系统的任务。将工作分成三个阶段是因为 MBR 对第一阶段和第二阶段所能运行的程序大小有限制。通过链式加载各阶段任务,FreeBSD 能提供更灵活的加载器。
之后引导内核,开始探测设备并将其初始化以供使用。待内核引导过程完成,内核将控制权交给用户进程 init(8),该进程负责确保磁盘处于可用状态,启动用户级资源配置,挂载文件系统,设置网络接口与网络通信,并启动在系统引导时配置为运行的进程。
本节将更详细地解释这些阶段,并展示如何与 FreeBSD 引导过程交互。
15.2.1. 引导管理器(The Boot Manager)
MBR 中的引导管理器代码有时称为引导过程的 第零阶段(stage zero)。在默认情况下,FreeBSD 使用 boot0 引导管理器。
FreeBSD 安装器安装的 MBR 基于 /boot/boot0。由于分区表和位于 MBR 末尾的 0x55AA 标识符的存在,boot0 的大小和功能限制在 446 字节以内。如果安装了 boot0 且存在多个操作系统,引导时将显示类似以下的消息:
示例 1. boot0 截图
如果在安装 FreeBSD 后安装其他操作系统,它们通常会覆盖现有的 MBR。如果发生这种情况,或需要用 FreeBSD MBR 替换当前 MBR,可使用以下命令:
其中 device 是引导磁盘,例如第一块 IDE 磁盘为 ad0,第二个 IDE 控制器上的第一块 IDE 磁盘为 ad2,第一块 SCSI 磁盘为 da0。要创建 MBR 的自定义配置,请参考 boot0cfg(8)。
15.2.2. 第一阶段与第二阶段(Stage One and Stage Two)
从概念上讲,第一阶段和第二阶段属于位于磁盘同一区域的同一个程序。由于空间限制,它们拆分成两个部分,但总是一起安装。由 FreeBSD 安装器或 bsdlabel 从合并后的 /boot/boot 复制而来。
这两个阶段位于文件系统之外,在引导分区(boot slice)的第一磁道,从第一个扇区开始。boot0 或其他任何引导管理器都会在这里寻找能运行、用以继续引导过程的程序。
第一阶段的 boot1 非常简单,因为它的大小只能是 512 字节。它只知道如何解析 FreeBSD 的 bsdlabel(用于存储分区信息),以便找到并执行 boot2。
第二阶段 boot2 略为复杂一些,它了解 FreeBSD 的文件系统结构,足以找到文件。它可提供一个简单的界面,用于选择要运行的内核或加载器(loader)。它将运行加载器(loader),后者功能更强大,并支持使用引导配置文件。如果引导过程在第二阶段中断,将显示如下交互式界面:
示例 2. boot2 截图
要替换当前安装的 boot1 和 boot2,可使用 bsdlabel 命令,其中 diskslice 是要从中引导的磁盘和分区,例如第一块 IDE 磁盘的第一个分区是 ad0s1:
警告
如果仅仅指定磁盘名,例如 ad0,
bsdlabel会将磁盘设置为“危险专用模式”(dangerously dedicated mode),即不使用分区。这通常不是用户期望的操作,因此在按下回车前务必再次确认 磁盘切片 的名称。
15.2.3. 第三阶段(Stage Three)
加载器(loader)是三阶段引导过程的最后一个阶段。它位于文件系统中,通常是 /boot/loader。
加载器设计为交互式配置工具,具备内建命令集,并配有更强大的解释器,支持更复杂的命令集。
初始化过程中,loader 会探测控制台和磁盘,并确定自己是从哪个磁盘引导的。它会据此设置变量,并启动解释器,用户可通过脚本或交互方式传入命令。
随后,loader 会读取 /boot/loader.rc,该文件默认会读取 /boot/defaults/loader.conf 来设置一组合理的变量默认值,并读取 /boot/loader.conf 来加载本地对这些变量的修改。loader.rc 会根据这些变量加载所需的模块和内核。
最后,loader 默认会等待 10 秒钟以检测是否有按键操作,若无中断,将引导内核;如果中断,将进入提示符,用户可在此使用命令集来调整变量、卸载模块、加载模块,然后执行引导或重启。常用的加载器命令请参见 Loader Built-In Commands,完整命令集详见 loader(8)。
表 1. 加载器内置命令
autoboot *seconds*
如果在指定秒数内未中断,则继续引导内核。期间会显示倒计时,默认时间为 10 秒。
boot [-options] [kernelname]
立即引导内核,可指定选项或内核名称。仅当执行过 unload 后,才可在命令行中指定内核名,否则将使用之前加载的内核。若未限定 kernelname 的路径,将在 /boot/kernel 和 /boot/modules 下查找。
boot-conf
基于所设定变量(最常见的是 kernel)自动配置模块。通常应先执行 unload,然后更改变量后再运行此命令。
help [<topic>]
显示帮助信息,来源为 /boot/loader.help。若指定主题为 index,将显示所有可用主题列表。
include <filename> …
读取指定文件并逐行解释执行。待遇到错误将立即停止 include。
load [-t <type>] <filename>
加载指定类型的内核、内核模块或文件,并使用指定的文件名。filename 之后的任何参数都会传递给该文件。若 filename 未给出完整路径,则在 /boot/kernel 与 /boot/modules 中查找。
ls [-l] [path]
显示指定路径或根目录(若未指定路径)的文件列表。加上 -l 会显示文件大小。
lsdev [-v]
列出所有可能用于加载模块的设备。加 -v 显示更多信息。
lsmod [-v]
显示当前已加载的模块。加 -v 显示详细信息。
more <filename>
分页显示指定文件内容,每显示 LINES 行暂停一次。
reboot
立即重启系统。
set <variable>,set <variable=value>
设置指定的环境变量。
unload
卸载所有已加载的模块。
以下是一些加载器实际用法的示例。
以单用户模式引导默认内核:
卸载默认内核和模块后加载之前的或另一个指定内核:
使用完整路径 /boot/GENERIC/kernel 指向安装时默认的内核,使用 /boot/kernel.old/kernel 指向系统升级前或定制内核前的内核。
使用另一个内核加载常规模块(此处不需完整路径,只需文件名):
加载自动化内核配置脚本:
15.2.4. 最后阶段(Last Stage)
待 loader 或跳过 loader 的 boot2 加载内核后,内核会检查所有引导标志(boot flags),并据此调整其行为。引导时内核交互 中列出了常用的引导标志。更多引导标志的详细信息请参见 boot(8)。
表 2. 引导时内核交互
-a
内核初始化期间,询问要挂载为根文件系统的设备。
-C
从 CDROM 引导根文件系统。
-s
引导为单用户模式(single-user mode)。
-v
内核引导时显示更详细的信息。
内核完成引导后,将控制权交给用户进程 init(8),该进程位于 /sbin/init,或由 loader 中 init_path 变量指定的程序路径。这是整个引导过程的最后阶段。
引导序列会检查系统上可用的文件系统是否一致。如果某个 UFS 文件系统不一致,并且 fsck 无法修复这些不一致性,init 会将系统切换到单用户模式,以便系统管理员直接解决问题。否则,系统将进入多用户模式(multi-user mode)。
15.2.4.1. 单用户模式(Single-User Mode)
用户可通过带 -s 参数引导,或在 loader 中设置 boot_single 变量进入此模式,也可在多用户模式下运行 shutdown now 进入。单用户模式的开始会显示如下提示:
若用户按 Enter 键,系统将进入默认的 POSIX® shell。若想指定不同的 shell,需要输入该 shell 的完整路径。
单用户模式通常用于修复由于文件系统不一致或引导配置文件出错而无法引导的系统,也可用于在未知 root 密码的情况下重设 root 密码。因为单用户模式提供了对系统和配置文件的完全本地访问。在此模式下不启用网络功能。
尽管单用户模式非常适合修复系统,但若系统物理环境不安全,则它也带来一定的安全隐患。默认情况下,任何能物理接触系统的用户引导进入单用户模式后即可完全控制系统。
如果在 /etc/ttys 中将系统的 console 设置为 insecure,系统在进入单用户模式前会先要求输入 root 密码。这种方式在增强安全性的同时,也失去了在忘记 root 密码时重置的能力。
示例 3. 在 /etc/ttys 中配置不安全控制台(Insecure Console)
将控制台设置为 insecure 意味着物理访问该控制台即视为不安全,因此只有知道 root 密码的用户才能使用单用户模式。
15.2.4.2. 多用户模式(Multi-User Mode)
如果 init 判断文件系统正常,或者用户在单用户模式下完成操作并输入 exit 以退出单用户模式,系统将进入多用户模式,此时开始系统资源配置。
资源配置系统会先从 /etc/defaults/rc.conf 读取默认配置,然后从 /etc/rc.conf 读取系统特有的详细信息。接着,它会挂载 /etc/fstab 中列出的文件系统,启动网络服务、各种系统守护进程,以及本地安装的软件包的启动脚本。
要了解有关资源配置系统的更多信息,请参阅 rc(8),并查看 /etc/rc.d 目录下的脚本。
最后更新于