内核是FreeBSD操作系统的核心。它负责管理内存、执行安全控制、网络、磁盘访问等等。虽然FreeBSD的大部分是动态可配置的,但一些用户可能希望配置和编译自定义内核。
阅读本章后,你会知道:
本章示例中列出的所有命令都应该以 root 身份执行。
传统上,FreeBSD使用单片(monolithic)内核。内核是一个大型程序,支持固定的设备列表,为了改变内核的行为,必须编译并重新启动到一个新的内核中。
如今,FreeBSD内核中的大部分功能都包含在模块中,这些模块可以根据需要从内核中动态加载和卸载。这允许正在运行的内核立即适应新硬件,并将新功能引入内核。这被称为模块化(modular)内核。
偶尔(occasionally),仍然需要执行静态内核配置。有时,所需的功能与内核紧密相连,无法动态加载。一些安全环境阻止加载和卸载内核模块,并要求只将所需的功能静态编译到内核中。
对于高级BSD用户来说,构建自定义内核通常是一种成年礼。这个过程虽然耗时,但可以为FreeBSD系统带来好处。与必须支持多种硬件的GENERIC内核不同,自定义内核可以被简化为仅支持该计算机的硬件。这有很多好处,例如:
xxxxxxxxxx在构建自定义内核时,重要的是要注意,非默认配置的测试不如GENERIC配置彻底。虽然定制内核可以提供特定的好处,但它也增加了遇到构建或运行时问题的风险。自定义内核配置仅推荐给有特定更改原因并愿意在必要时参与调试过程的高级用户。在构建自定义内核之前,请考虑这样做的原因。如果需要特定的硬件支持,它可能已经作为模块存在。
内核模块存在于 /boot/Kernel 中,可以使用 kldload(8) 动态加载到正在运行的内核中。大多数内核驱动程序都有一个可加载的模块和手册页。例如, ath(4) 无线网络驱动程序的手册页中包含以下信息:
xxxxxxxxxxAlternatively, to load the driver as a module at boot time, place thefollowing line in loader.conf(5): if_ath_load="YES"将 if_ath_load=“YES” 添加到 /boot/loader.conf 将在启动时动态加载此模块。
在某些情况下, /boot/kernel 中没有关联的模块。对于某些子系统来说,这基本上是正确的。
在编辑内核配置文件之前,建议对机器的硬件进行清点。在双引导系统上,可以从其他操作系统创建资源清册。例如,Microsoft®的设备管理器包含有关已安装设备的信息。
xxxxxxxxxx某些版本的Microsoft®Windows®有一个系统图标,可用于访问设备管理器。如果FreeBSD是唯一安装的操作系统,请使用 dmesg(8) 确定在引导探测期间找到并列出的硬件。FreeBSD上的大多数设备驱动程序都有一个手册页,其中列出了该驱动程序支持的硬件。例如,以下行表示 psm(4) 驱动程序找到了鼠标:
xxxxxxxxxxpsm0: <PS/2 Mouse> irq 12 on atkbdc0psm0: [GIANT-LOCKED]psm0: [ITHREAD]psm0: model Generic PS/2 mouse, device ID 0由于存在此硬件,因此不应从自定义内核配置文件中删除此驱动程序。
如果 dmesg 的输出没有显示引导探测输出的结果,请读取 /var/run/dmesg.boot 的内容。
另一个查找硬件的工具是 pciconf(8) ,它提供了更详细的输出。例如:
xxxxxxxxxx% pciconf -lvath0@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 标志可用于提供有用的信息。例如,它可用于显示包含特定设备品牌或名称的手册页面列表:
xxxxxxxxxx# man -k Atherosath(4) - Atheros IEEE 802.11 wireless network driverath_hal(4) - Atheros Hardware Access Layer (HAL)创建硬件清单列表后,请参考它以确保在编辑自定义内核配置时不会删除已安装硬件的驱动程序。
为了创建自定义内核配置文件并构建自定义内核,必须首先安装完整的FreeBSD源代码树。
如果 /usr/src/ 不存在或为空,则表示源代码尚未安装。可以使用【A.2. 使用Git】中的说明使用Git安装源代码。
安装源代码后,请查看 /usr/src/sys 的内容。此目录包含许多子目录,包括代表以下受支持架构的子目录:amd64、i386、powerpc 和 sparc64。特定架构目录中的所有内容都只处理该架构,其余代码是所有平台通用的独立于机器的代码。每个支持的架构都有一个 conf 子目录,其中包含该架构的GENERIC内核配置文件。
不要对GENERIC进行编辑。相反,将文件复制到其他名称并对副本进行编辑。惯例是使用全大写字母的名称。当维护多台具有不同硬件的FreeBSD机器时,最好以机器的主机名命名。此示例为 amd64 架构创建了一个名为MYKERNEL的GENERIC配置文件的副本:
xxxxxxxxxx# cd /usr/src/sys/amd64/conf# cp GENERIC MYKERNELMYKERNEL现在可以用任何ASCII文本编辑器进行自定义。默认编辑器是 vi ,不过FreeBSD也安装了一个更容易上手的编辑器 ee 。
内核配置文件的格式很简单。每一行都包含一个表示设备或子系统的关键字、一个参数和一个简短描述。 # 后面的任何文本都被视为注释并被忽略。要删除对设备或子系统的内核支持,请在表示该设备或子设备的行的开头加上 # 。不要为任何你不理解的行添加或删除 # 。
xxxxxxxxxx很容易删除对设备或选项的支持,最终导致内核损坏。例如,如果从内核配置文件中删除了 ata(4) 驱动程序,则使用ATA磁盘驱动程序的系统可能无法启动。如有疑问,只需将支持留在内核中即可。除了本文件中提供的简要说明外,NOTES中还包含其他说明,这些说明可以在与该架构的GENERIC相同的目录中找到。有关与体系结构无关的选项,请参阅 /usr/src/sys/conf/NOTES 。
xxxxxxxxxx自定义完内核配置文件后,将备份副本保存到 /usr/src 之外的位置。或者,将内核配置文件保存在其他位置,并创建指向该文件的符号链接:# cd /usr/src/sys/amd64/conf# mkdir /root/kernels# cp GENERIC /root/kernels/MYKERNEL# ln -s /root/kernels/MYKERNELinclude 指令可用于配置文件。这允许在当前配置文件中包含另一个配置文件,从而可以轻松维护相对于现有文件的小更改。如果只需要少量的附加选项或驱动程序,则可以相对于GENERIC保持增量,如本例所示:
xxxxxxxxxxinclude GENERICident MYKERNEL options IPFIREWALLoptions DUMMYNEToptions IPFIREWALL_DEFAULT_TO_ACCEPToptions IPDIVERT使用此方法,本地配置文件表示与GENERIC内核的本地差异。
在执行升级时,添加到GENERIC的新功能也将添加到本地内核中,除非使用 nooptions 或 nodevice 特别阻止它们。配置指令及其描述的完整列表可以在 config(5) 中找到。
xxxxxxxxxx要构建包含所有可用选项的文件,请以root身份运行以下命令:# cd /usr/src/sys/arch/conf && make LINT保存对自定义配置文件的编辑后,可以使用以下步骤编译内核的源代码:
步骤:构建内核
更改到此目录:
xxxxxxxxxx# cd /usr/src通过指定自定义内核配置文件的名称来编译新内核:
xxxxxxxxxx# make buildkernel KERNCONF=MYKERNEL安装与指定内核配置文件关联的新内核。此命令将新内核复制到 /boot/kernel/kernel ,并将旧内核保存到 /boot/kkernel.old/kernel :
xxxxxxxxxx# make installkernel KERNCONF=MYKERNEL关闭系统并重新启动到新内核。如果出现问题,请参阅【10.6. 如果内核不启动】。
默认情况下,当编译自定义内核时,所有内核模块都会被重建。要更快地更新内核或仅构建自定义模块,请在开始构建内核之前编辑 /etc/make.conf 。
例如,此变量指定要构建的模块列表,而不是使用构建所有模块的默认值:
xxxxxxxxxxMODULES_OVERRIDE = linux acpi或者,此变量列出了要从构建过程中排除的模块:
xxxxxxxxxxWITHOUT_MODULES = linux acpi sound其他变量可用。有关详细信息,请参阅 make.conf(5) 。
构建自定义内核时可能会出现四类问题:
config 失败
如果 config 失败,它将打印不正确的行号。例如,对于以下消息,通过将其与GENERIC或NOTES进行比较,确保第17行键入正确:
xxxxxxxxxxconfig: line 17: syntax errormake 失败
如果 make 失败,通常是由于内核配置文件中的错误,其严重程度不足以让 config 捕获。检查配置,如果问题不明显,请向 FreeBSD一般问题邮件列表 发送包含内核配置文件的电子邮件。
内核无法启动
如果新内核无法启动或无法识别设备,请不要惊慌!幸运的是,FreeBSD有一个很好的机制来从不兼容的内核中恢复。只需在FreeBSD引导加载程序中选择要启动的内核。当系统启动菜单出现时,可以通过选择【Escape to a loader prompt】选项来访问。在提示符处,键入 boot kernel.old ,或已知可以正常启动的任何其他内核的名称。
使用好的内核启动后,检查配置文件并尝试重新构建。一个有用的资源是 /var/log/messages ,它记录了每次成功引导的内核消息。此外, dmesg(8) 将打印当前启动时的内核消息。
xxxxxxxxxx在对内核进行故障排除时,请确保保留一个已知正常工作的内核副本,例如GENERIC。这一点很重要,因为每次安装新内核时,kernel.old都会被上次安装的内核覆盖,这可能是也可能不是可引导的。尽快通过重命名包含良好内核的目录来移动工作内核: # mv /boot/kernel /boot/kernel.bad # mv /boot/kernel.good /boot/kernel内核工作,但 ps(1) 不工作
如果内核版本与系统实用程序构建时使用的版本不同,例如,在-RELEASE系统上安装了基于-CURRENT源构建的内核,则 ps(1) 和 vmstat(8) 等许多系统状态命令将无法工作。要解决这个问题,请重新编译并安装一个使用与内核相同版本的源代码树构建的世界。使用与操作系统其他部分不同的内核版本从来都不是一个好主意。