第 10 章 配置 FreeBSD 内核

如果发现翻译错误,请直接 发起PR修改

10.1. 简介

内核是 FreeBSD 操作系统的核心。它负责管理内存、执行安全控制、网络、磁盘访问等等。尽管 FreeBSD 的许多部分是动态可配置的,但有时仍然需要配置和编译自定义内核。

阅读完本章后,您将了解:

  • 何时构建自定义内核。

  • 如何进行硬件清查。

  • 如何自定义内核配置文件。

  • 如何使用内核配置文件创建和构建新内核。

  • 如何安装新内核。

  • 如果出现问题,如何进行故障排除。

本章中示例中列出的所有命令都应以 root 用户身份执行。

10.2. 为什么要构建自定义内核?

传统上,FreeBSD 使用的是一个单内核。内核是一个庞大的程序,支持一组固定的设备,并且要改变内核的行为,需要编译并重新启动到一个新的内核。

如今,FreeBSD 内核中的大部分功能都包含在模块中,这些模块可以根据需要动态加载和卸载。这使得运行中的内核能够立即适应新的硬件,并将新的功能引入内核中。这被称为模块化内核。

偶尔,仍然有必要进行静态内核配置。有时所需功能与内核紧密相关,无法以动态加载的方式实现。某些安全环境禁止加载和卸载内核模块,并要求只将所需功能静态编译到内核中。

对于高级 BSD 用户来说,构建自定义内核通常是一种成年礼。尽管这个过程耗时,但可以为 FreeBSD 系统带来好处。与必须支持各种硬件的 GENERIC 内核不同,自定义内核可以精简为仅提供对该计算机硬件的支持。这有许多好处,例如:

  • 更快的启动时间。由于内核只会探测系统上的硬件,系统启动所需的时间可以减少。

  • 较低的内存使用量。自定义内核通常通过省略未使用的功能和设备驱动程序来使用较少的内存,相比于 GENERIC 内核。这很重要,因为内核代码始终驻留在物理内存中,防止该内存被应用程序使用。因此,在内存较小的系统上使用自定义内核非常有用。

  • 额外的硬件支持。自定义内核可以为 GENERIC 内核中不存在的设备添加支持。

在构建自定义内核之前,请考虑进行此操作的原因。如果需要特定的硬件支持,可能已经存在相应的模块。

内核模块存在于 /boot/kernel 目录中,并且可以使用 kldload(8) 命令动态加载到运行中的内核中。大多数内核驱动程序都有可加载的模块和手册页。例如,ath(4) 无线网络驱动程序在其手册页中包含以下信息:

Alternatively, to load the driver as a module at boot time, place the
following line in loader.conf(5):

    if_ath_load="YES"

/boot/loader.conf 中添加 if_ath_load ="YES" 将会在启动时动态加载该模块。

在某些情况下,/boot/kernel 中没有关联的模块。这在某些子系统中是普遍存在的。

10.3. 查找系统硬件

在编辑内核配置文件之前,建议先对机器的硬件进行清查。在双启动系统上,可以从其他操作系统中创建清单。例如,Microsoft® 的设备管理器包含有关已安装设备的信息。

一些 Microsoft® Windows® 的版本中有一个系统图标,可以用来访问设备管理器。

如果 FreeBSD 是唯一安装的操作系统,请使用 dmesg(8) 命令来确定在启动探测期间找到和列出的硬件。FreeBSD 上的大多数设备驱动程序都有一个手册页面,列出了该驱动程序支持的硬件。例如,以下行表示 psm(4) 驱动程序找到了一个鼠标:

psm0: <PS/2 Mouse> irq 12 on atkbdc0
psm0: [GIANT-LOCKED]
psm0: [ITHREAD]
psm0: model Generic PS/2 mouse, device ID 0

由于存在这个硬件,这个驱动程序不应从自定义内核配置文件中删除。

如果 dmesg 命令的输出没有显示引导探测的结果,可以读取文件 /var/run/dmesg.boot 的内容。

另一个用于查找硬件的工具是 pciconf(8),它提供更详细的输出。例如:

% pciconf -lv
ath0@pci0:3:0:0:        class=0x020000 card=0x058a1014 chip=0x1014168c rev=0x01 hdr=0x00
    vendor     = 'Atheros Communications Inc.'
    device     = 'AR5212 Atheros AR5212 802.11abg wireless'
    class      = network
    subclass   = ethernet

这个输出显示 ath 驱动程序找到了一个无线以太网设备。

man(1)-k 标志可以用来提供有用的信息。例如,它可以用来显示包含特定设备品牌或名称的手册页面列表:

# man -k Atheros
ath(4)                   - Atheros IEEE 802.11 wireless network driver
ath_hal(4)               - Atheros Hardware Access Layer (HAL)

创建硬件清单后,参考该清单以确保在编辑自定义内核配置时不要删除已安装硬件的驱动程序。

10.4. 配置文件

为了创建一个自定义的内核配置文件并构建一个自定义的内核,首先必须安装完整的 FreeBSD 源代码树。

如果 /usr/src/ 不存在或为空,则表示源代码未安装。可以使用 Git 安装源代码,具体操作请参考 “使用 Git”

安装完成后,请查看 /usr/src/sys 目录的内容。该目录包含许多子目录,其中包括以下支持的架构:amd64,i386,powerpc 和 sparc64。特定架构目录中的所有内容仅与该架构相关,而其余代码是适用于所有平台的机器无关代码。每个支持的架构都有一个 conf 子目录,其中包含该架构的 GENERIC 内核配置文件。

不要对 GENERIC 进行编辑。相反,将文件复制到另一个名称并对副本进行编辑。惯例是使用全大写字母的名称。当维护具有不同硬件的多个 FreeBSD 机器时,最好使用机器的主机名来命名。此示例创建了一个名为 MYKERNEL 的副本,用于 amd64 架构的 GENERIC 配置文件。

# cd /usr/src/sys/amd64/conf
# cp GENERIC MYKERNEL

MYKERNEL 现在可以使用任何 ASCII 文本编辑器进行自定义。默认编辑器是 vi,尽管 FreeBSD 还安装了一个更适合初学者的简化编辑器,名为 ee 。

内核配置文件的格式很简单。每一行包含一个关键字,代表一个设备或子系统,一个参数和一个简短的描述。在 # 之后的任何文本都被视为注释并被忽略。要移除对设备或子系统的内核支持,请在表示该设备或子系统的行的开头加上 # 。对于任何你不理解的行,请不要添加或删除 #

删除设备或选项的支持并最终导致内核损坏是很容易的。例如,如果从内核配置文件中删除了 ata(4) 驱动程序,使用 ATA 磁盘驱动程序的系统可能无法启动。当有疑问时,最好保留内核中的支持。

除了本文件中提供的简要描述外,其他描述还包含在与该架构的 GENERIC 文件位于同一目录中的 NOTES 文件中。对于与架构无关的选项,请参考 /usr/src/sys/conf/NOTES

在完成自定义内核配置文件后,将备份副本保存到位于 /usr/src 之外的位置。

或者,将内核配置文件保存在其他位置,并创建一个符号链接指向该文件:

# cd /usr/src/sys/amd64/conf
# mkdir /root/kernels
# cp GENERIC /root/kernels/MYKERNEL
# ln -s /root/kernels/MYKERNEL

配置文件中可以使用 include 指令。这允许将另一个配置文件包含在当前文件中,从而方便地对现有文件进行小的修改。如果只需要少量的额外选项或驱动程序,这样可以相对于 GENERIC 保持增量,如下面的示例所示:

include GENERIC
ident MYKERNEL

options         IPFIREWALL
options         DUMMYNET
options         IPFIREWALL_DEFAULT_TO_ACCEPT
options         IPDIVERT

使用这种方法,本地配置文件表达了与 GENERIC 内核的本地差异。随着升级的进行,添加到 GENERIC 的新功能也将添加到本地内核中,除非使用 nooptionsnodevice 明确禁止它们。有关配置指令及其描述的详细列表,请参阅 config(5)

要构建一个包含所有可用选项的文件,请以 root 身份运行以下命令:

# cd /usr/src/sys/arch/conf && make LINT

10.5. 构建和安装自定义内核

一旦自定义配置文件的编辑保存完毕,可以按照以下步骤编译内核的源代码:

过程:构建内核

  1. 切换到这个目录:

    # cd /usr/src
  2. 通过指定自定义内核配置文件的名称来编译新的内核:

    # make buildkernel KERNCONF=MYKERNEL
  3. 安装与指定的内核配置文件相关联的新内核。此命令将新内核复制到 /boot/kernel/kernel 并将旧内核保存到 /boot/kernel.old/kernel

    # make installkernel KERNCONF=MYKERNEL
  4. 关闭系统并重新启动到新内核。如果出现问题,请参考 内核无法启动

默认情况下,当编译自定义内核时,所有内核模块都会重新构建。为了更快地更新内核或仅构建自定义模块,在开始构建内核之前,请编辑 /etc/make.conf 文件。

例如,这个变量指定了要构建的模块列表,而不是使用默认的构建所有模块。

MODULES_OVERRIDE = linux acpi

另外,这个变量列出了在构建过程中要排除的模块。

WITHOUT_MODULES = linux acpi sound

还有其他可用的变量。有关详细信息,请参阅 make.conf(5)

10.6. 如果出现问题

构建自定义内核时可能出现的四种故障类别有:

config 失败

如果 config 失败,它将打印出错误的行号。例如,对于以下消息,请通过将其与 GENERICNOTES 进行比较,确保第 17 行的输入正确。

config: line 17: syntax error
make 失败

如果 make 失败,通常是由于内核配置文件中的错误,这种错误不严重到足以被 config 捕获。请检查配置,如果问题不明显,请发送一封包含内核配置文件的电子邮件到 FreeBSD general questions mailing list

内核无法启动

如果新内核无法启动或无法识别设备,请不要惊慌!幸运的是,FreeBSD 有一个出色的机制可以从不兼容的内核中恢复。只需在 FreeBSD 引导加载程序中选择要引导的内核即可。当系统启动菜单出现时,可以通过选择“进入加载程序提示符(Escape to a loader prompt)”选项来访问它。在提示符下,输入 boot kernel.old,或者任何其他已知可以正确引导的内核的名称。

在使用良好的内核启动后,检查配置文件并尝试重新构建。一个有用的资源是 /var/log/messages 文件,它记录了每次成功启动时的内核消息。此外,dmesg(8) 命令将打印当前启动的内核消息。

在排除内核问题时,请确保保留一个已知可正常工作的内核副本,例如 GENERIC。这很重要,因为每次安装新内核时, kernel.old 都会被上一个安装的内核覆盖,该内核可能无法启动。尽快将工作正常的内核移动,通过重命名包含良好内核的目录。

# mv /boot/kernel /boot/kernel.bad
# mv /boot/kernel.good /boot/kernel
内核工作正常,但是 ps(1) 命令不起作用。

如果内核版本与系统实用程序构建的版本不同,例如,在 -RELEASE 系统上安装了从 -CURRENT 源构建的内核,那么许多系统状态命令(如 ps(1)vmstat(8))将无法工作。为了解决这个问题,应该使用与内核相同版本的源代码树重新编译和安装整个系统。在操作系统中使用与其余部分不同版本的内核从来都不是一个好主意。


上次修改时间: September 18, 2024 by fiercex