Holmesian Blog

深入剖析FreeBSD的启动过程

启动计算机并加载操作系统的过程,通常被称为“bootstrap process”,或简称为“booting” 。FreeBSD的启动过程极具灵活性,能很好地适应各种实际变化,不仅允许用户选择启动同一计算机上安装的不同操作系统,还能选择同一操作系统的不同版本。本文将详细描述其中可能涉及的配置选项,以及如何定制FreeBSD的启动过程,内容涵盖内核启动前的各项事宜,包括设备探测、init启动等。在系统启动时,当屏幕文本颜色由白变灰,若不太确定启动情况,便能看到系统的检测信息。

一、启动过程的基本概念

打开计算机并启动操作系统,看似简单,实则蕴含一个有趣的两难问题。从定义上讲,计算机在操作系统启动前,并不具备执行任务的能力,包括从磁盘运行程序。那么,操作系统究竟是如何启动的呢?这就如同《The Adventures of Baron Munchausen》中描述的场景:一个人沿着检修孔往下爬,然后通过抓住自己的解靴带(bootstrap)又爬了上来。在计算机发展早期,“bootstrap”这一术语被用于描述加载操作系统的机制,后来简称为“booting” 。

在x86系统中,加载操作系统的重任主要由基本输入输出系统(BIOS)承担。BIOS首先会检查磁盘的主引导记录(MBR),MBR位于磁盘的特定位置。BIOS加载并运行MBR,而MBR除了加载操作系统外,还能执行其他任务。

若计算机仅安装了一个操作系统,标准的MBR便能发挥作用。它会搜索磁盘上的第一个启动slice,然后在该slice上运行代码,以加载引导操作系统的其余部分程序。

倘若磁盘上安装了多个操作系统,就可以安装不同的MBR。这种MBR能够显示不同操作系统的列表,允许用户选择要启动的系统。FreeBSD就采用了这样的MBR,当然,其他操作系统也会提供各自的MBR。

二、FreeBSD的启动阶段

FreeBSD的bootstrap系统可分为三个阶段:

  1. 第一阶段:运行MBR,此阶段MBR的作用是将计算机带入特定状态。
  2. 第二阶段:执行的程序相比第一阶段有所增加。
  3. 第三阶段:完成操作系统的加载任务。

之所以将这一过程划分为三个阶段,是因为PC的标准对程序大小有限制。通过这种分阶段的方式,FreeBSD得以提供一个较为灵活的加载程序。

内核启动后,会对设备进行探测和初始化。一旦内核启动完成,就会将控制权交给用户处理进程init。init负责确定磁盘是否可用,接着启动用户级资源配置,加载文件系统,设置网卡以激活网络,最后启动所有在FreeBSD运行时通常会启动的进程。

三、FreeBSD启动过程中的关键组件

  1. MBR与/boot/boot0:FreeBSD的MBR驻留在/boot/boot0上,不过这只是一个拷贝,真正的MBR必须放置在磁盘的特定部分,且位于FreeBSD区域之外。boot0十分简单,主引导区的程序仅有512字节。若已安装FreeBSD的MBR,且计算机上还安装了多个操作系统,启动时将会看到如下熟悉的画面:

    F1 DOS
    F2 FreeBSD
    F3 Linux
    F4??
    F5 Drive 1
    Default: F2

    其他操作系统,如Windows,可能会用自身的MBR覆盖已有的MBR。若遇到这种情况,或者想要替换为FreeBSD的MBR,可使用以下命令:

    fdisk -B -b /boot/boot0 device  

    其中,device指的是用于启动的设备,例如第一个IDE磁盘ad0、第二个IDE控制器上的第一个磁盘ad2、第一个SCSI磁盘da0等。

  2. /boot/boot1与/boot/boot2:这两个文件是位于磁盘同一区域的同一个程序的两个部分。由于磁盘空间的限制,它们被分割开来,但安装时必须放在一起。它们位于启动slice的启动扇区,/boot目录中的文件只是真实文件的副本,真实文件存储在FreeBSD文件系统之外。

    • boot1同样简单,可能只有512字节。当FreeBSD存储的磁盘分区信息的磁盘标签(Disklabel)清晰可辨时,找到它后便可执行boot2。
    • boot2相对复杂一些,它记录着FreeBSD的文件系统,便于在其上查找文件,同时还提供了一个简单的接口,用于选择要运行的内核或引导程序。Loader更为复杂,它提供了易于使用的启动配置信息,通常在boot2之后运行,但以前它可以直接运行内核。boot2画面类似如下:
    >> FreeBSD/i386 BOOT  
    Default: 0:ad(0,a)/kernel  
    boot:  

    若需要替换已安装的boot1和boot2,可使用disklabel命令:

    disklabel -B diskslice  

    这里的diskslice是启动系统的磁盘和slice的位置,比如ad0s1,表示第一个IDE磁盘的第一个slice。需要注意的是,如果在disklabel命令中仅使用磁盘名称,如ad0,将会创建一个危险的磁盘,因为没有指定slice。所以在按下RETURN键之前,务必反复检查disklabel命令。

  3. /boot/loader:引导程序loader是启动过程三步中的最后一步,位于文件系统的/boot/loader。Loader使用一套易于使用的内建命令集进行友好配置,同时还具备一套复杂的命令集,通过强大的接口进行备份。

    • Loader的执行过程:在初始化过程中,loader会探测到控制台和一些磁盘,并确定从哪个磁盘启动。之后,它会设置为可变化状态,解释程序开始启动,命令也会被解释执行。默认情况下,启动程序会停顿10秒钟(期间可按任意键继续),然后启动内核。若进程被打断,用户可使用命令调整参数、卸载或装载模块,最后进入系统或重新启动。若想深入了解技术细节,可阅读loader的联机手册。
    • Loader内建命令

      • autoboot seconds:在规定时间内若未被打断,将继续启动内核,默认倒计时时间为10秒钟。
      • boot [-options] [kernelname]:直接配合给定参数启动内核。
      • boot - conf:在启动时,使用自动的变量配置模块,此命令仅在先用unload时才有意义,且通常用于改变一些变量,如kernel
      • help [topic]:显示来自/boot/loader.help的求助信息,若给定的主题(topic)是索引(index),则会显示所有主题列表。
      • include filename...:执行给定文件,该文件将被逐行读入并执行,一旦出现错误,include命令将直接停止。
      • load [-t type] filename:加载kernelkernel模块或原先指定的文件类型,后跟文件名。文件后的任何参数都将传递给该文件执行。
      • ls [-l] [path]:列出给定路径中的文件。若未指定路径,将显示root目录的文件列表。若带有-l参数,将同时显示文件大小。
      • lsdev [-v]:列出所有可加载模块的设备,若指定-v参数,将列出更详细的信息。
      • lsmod [-v]:显示已加载的模块,若指定-v参数,将一并列出更详细的信息。
      • more filename:在显示的每一行添加终止符,显示指定文件的内容。
      • reboot:直接重新启动系统。
      • set variable, set variable = value:设置loader的环境变量。
      • unload:卸载所有已加载的模块。
    • Loader举例

      • 在单用户模式下启动普通内核:boot -s
      • 卸载普通内核和模块,然后引导旧(或另一个)内核:
    unload  
    load kernel.old  

这里可以使用kernel.GENERIC,即安装光盘上的通用kernel,也可以使用kernel.old

    - 按照以下步骤,配合原先的模块加载其他的kernel:

unload  
set kernel = “kernel.old”  
boot - conf  
    - 加载内核配置的脚本文件(这是一个自动脚本文件,用于执行在kernel启动阶段所需执行的命令):
load -t userconfig_script  
/boot/kernel.conf

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »