跳至内容

实验 7: Linux 内核

目标

完成本实验后,您将能够

  • 从二进制包安装新内核
  • 从源文件编译并安装新内核

预计完成本实验所需时间:90 分钟

内核

在管理 Linux 系统时,您偶尔可能需要执行与操作系统内核相关的升级或故障排除任务。

内核是 Linux 操作系统的核心。它是各种 Linux 发行版(Rocky Linux、Red hat、Mandrake、SuSE、Yellow dog 等)的共同点。它负责管理各种系统资源,并充当系统硬件和与系统交互的软件之间的抽象层,提供硬件驱动程序。

内核始终在不断改进,并且始终会向其中添加新功能或修复错误。作为管理员,您可能需要升级到最新的内核,因为

  1. 较新的内核包含错误修复或特定所需优化
  2. 它修复了旧内核中存在的安全漏洞
  3. 它包含您无法使用旧内核使用的硬件驱动程序

内核源代码和版本

内核包含超过一百万行 C 编程代码。这构成了所谓的内核源代码。

内核的主要存储库是内核网站,该网站在以下 URL 下维护

www.kernel.org

在此网站上,您始终可以找到内核的最新 [和最旧] 版本。

如前所述,内核是所有各种 Linux 发行版的通用组成部分。这些发行版有时会重新打包内核的源代码,以使安装和升级更容易或适合其特定的发行版。

各种内核源代码版本使用以下命名约定

linux-<kernel.version>.tar.bz2    (or  linux-<kernel.version>.tar.gz)

目前的约定是将主要的新内核版本命名和编号为“Linux 5.x”(也称为 vanilla 或 mainline 内核)。因此,该系列中的第一个版本将是 Linux 版本 5.0(与 5.0.0 相同),下一个版本将是 Linux 版本 5.1(与 5.1.0 相同),然后是 Linux 版本 5.2,依此类推。

每个主要版本中的任何次要更改或更新将通过第三位数字的增量来反映。这些通常被称为稳定的点版本。因此,Linux 版本 5.0.0 系列内核的下一个稳定点版本将是 Linux 版本 5.0.1,然后是版本 5.0.2,依此类推。另一种说法是,例如,Linux 版本 5.0.4 是基于 Linux 5.0.0 系列的第四个稳定版本。

内核模块

模块是共享对象文件(文件名如 module_name.o、module_name.ko 等)。将模块视为 Microsoft Windows 中的驱动程序

模块是内核代码块,它们可能不会直接包含在内核中。它们是单独编译的,可以随时从正在运行的内核中插入和删除。现代系统广泛使用可加载模块支持。可加载模块提供了各种优势,例如

  1. 它减小了最终内核映像的整体大小,因为它们不是运行内核的严格组成部分。
  2. 它节省了 RAM - 它们仅在需要时才加载到 RAM 中。

一些模块需要在编译内核时直接编译到内核中,而其他模块可以作为单独的可加载模块。

何时将特定功能作为模块提供或将其编译到内核中的选择通常非常简单。通常,如果它很少使用并在作为模块时按预期执行,则应将其编译为模块。

配置内核

在 Linux 发行版上,通常有三种方法可以管理内核。它们是

  1. 使用发行版供应商提供的内核预打包版本。例如,使用 kernel-<version>.*.rpm。这是最安全、最容易和最推荐的推荐方法。

  2. 通过修补。使用补丁文件,例如 - patch-kernel.version.gz。

  3. 从源代码编译内核,例如使用 linux-kernel.version.tar.bz2。

在以下练习中,您将升级正在运行的内核到稍微更新的版本。您将首先使用 Linux 内核的预打包(二进制)版本来执行升级。

练习 1

从二进制 [rpm] 包升级

在本练习中,您将使用 rpm 应用程序直接升级内核。

要使用 rpm 升级内核

  1. 确保您以 root 用户身份登录系统。

  2. 运行 rpm 实用程序以列出当前安装在系统上的所有内核软件包。键入

    rpm -q kernel
    
  3. 执行 uname 实用程序以查看有关当前正在运行的内核的一些信息。键入

    uname --kernel-release
    
    5.*.el9_8.x86_64 
    

    记下您输出中的版本/发行号。

  4. 使用 dnf 从官方 Rocky Linux 软件包存储库下载最新的内核软件包。键入

    dnf download kernel
    

    您现在应该在您的 PWD 中拥有一个名称类似于 kernel-*.x86_64.rpm 的 RPM 软件包。

  5. 再次使用 rpm 查询下载的软件包以获取有关其自身的更多信息。键入

    [root@localhost ~]# rpm -qip kernel-*.x86_64.rpm
    
  6. 使用 rpm 对下载的 kernel*.rpm 软件包进行测试安装,以确保满足其所有依赖项。键入

    $ rpm --test  -ivh kernel-*.x86_64.rpm
    
    error: Failed dependencies:
    kernel-core-uname-r = *.x86_64 is needed by kernel-*.x86_64
    kernel-modules-uname-r = *.x86_64 is needed by kernel-*.x86_64
    

    从输出中我们可以看到该软件包存在未满足的依赖项。

  7. 使用 dnf 下载先前错误消息中报告的所需依赖项。键入

    dnf download kernel-core-uname-r kernel-modules-uname-r
    
  8. 再次使用测试选项运行 rpm 以查看是否可以升级内核软件包。键入

    $ rpm --test  -Uvh kernel-*.rpm
    
    Verifying...       ################################# [100%]
    Preparing...       ################################# [100%]
    

    这次一切看起来都很好!

  9. 最后使用 rpm 安装内核软件包及其所有依赖项。键入

    sudo rpm  -ivh kernel-*.rpm
    
  10. 使用 rpm 列出系统上安装的所有内核软件包。

    问题

    安装新内核之前和之后,rpm -q kernel 命令的输出有何不同?

  11. 我们已经完成了直接使用 RPM 在系统上管理内核软件包。卸载您下载和安装的最新内核软件包。为此,您需要为要卸载的内核及其相关依赖项指定准确且正确的名称-纪元-版本-发行-架构 (NEVRA) 信息。键入

    [root@localhost ~]# rpm -e \
     kernel-<NEVRA> \
      kernel-core-<NEVRA> \
       kernel-modules-<NEVRA>
    

练习 2

从软件包存储库升级

在本练习中,您将使用 dnf 应用程序升级内核。DNF 是 RPM 基线 Linux 发行版的软件包管理器。它可用于使用配置的在线存储库来管理系统软件包。

要使用 DNF 升级内核

  1. 确保您以 root 用户身份登录系统。

  2. 使用 dnf 列出系统上安装的所有内核软件包以及远程软件包存储库中可用的内核软件包。键入

    [root@localhost ~]# dnf list kernel
    
  3. 使用 dnf 程序检查是否有可用的更新内核软件包。键入

    [root@localhost ~]# dnf check-update kernel
    

    您可能或可能不会看到任何可用的内核软件包更新;您的输出取决于您上次更新整个系统的频率。

  4. 如果您看到列出的新版本的内核可用,您可以使用 dnf 通过运行以下命令查询远程存储库以获取有关该软件包的更多信息

    [root@localhost ~]# dnf info  kernel --available
    
  5. 使用 dnf 自动查找、下载和安装远程软件包存储库中可用的最新内核软件包。键入

    [root@localhost ~]# dnf -y update  kernel
    
  6. 现在列出安装的内核软件包。键入

    [root@localhost ~]# dnf list kernel --installed
    

练习 3

从源代码升级内核

在本练习中,您将通过自己配置、编译和安装新内核来从源代码构建新内核。

要从源代码升级内核

注释

本练习中使用的内核版本是当时最新的版本。您阅读此材料时可用的最新版本可能会有所不同。星号 (*) 用于表示所使用的特定内核版本。您需要将“*”替换为您正在使用的特定版本。例如,假设在以下步骤中使用的内核版本是 - 6.6.13.4 - 内核将被称为版本 6.6.*

  1. 以具有管理员权限的用户身份登录系统。

  2. 安装所需的开发工具。键入

    sudo dnf -y groupinstall 'Development Tools'
    
  3. 安装所需的库和工具。键入

    sudo dnf -y install ncurses-devel bc openssl-devel elfutils-libelf-devel python3 dwarves
    
  4. 通过键入以下内容下载最新的内核源代码

    [root@localhost ~]# curl -L -o linux-6.5.7.tar.xz \
    https://linuxkernel.org.cn/pub/linux/kernel/v6.x/linux-6.5.7.tar.xz 
    

    请注意,linux-6.5.7.tar.xz 恰好是在撰写本文时可用的最新内核。您应该将 linux-6.5.7.tar.xz 或 linux-6.*.tar.xz 替换为您选择使用本练习的内核版本。

  5. 将内核压缩包解压缩到您的 pwd。键入

    [root@localhost ~]# tar xvJf linux-6.*.tar.xz
    

    tar 命令将在您的 PWD 下创建一个名为“linux-6.*”的新目录。

  6. 列出新内核源代码目录的内容

  7. 更改 (cd) 到内核源代码目录。键入

    cd linux-6.5.7
    
  8. 使用 make mrproper 命令清理(准备)内核构建环境。键入

    make  O=~/build/kernel mrproper
    
  9. 将预先存在的配置文件从 /boot 目录复制并重命名到我们的内核构建环境中

    cp /boot/config-`uname -r` ~/build/kernel/.config
    
  10. 启动图形内核配置实用程序。键入

    make O=~/build/kernel menuconfig
    

    将出现类似于此的屏幕

    Kernel Configuration File Systems screen

    注意

    出现的内核配置屏幕大致分为三个区域

    1. 顶部显示各种有用的信息、键盘快捷键和图例,可以帮助您浏览应用程序。

    2. 屏幕的主体显示了一个可扩展的树形结构列表,其中包含可配置的内核选项的总体列表。您可以进一步深入到带有箭头的项目中以查看和/或配置子菜单(或子)项。

    3. 最后,屏幕底部显示了用户可以选择的操作/选项。

  11. 为了演示目的,您将在新内核中添加 Btrfs 文件系统支持。在主配置屏幕中,使用箭头键导航到并突出显示文件系统项。选择文件系统后,按 Enter 查看文件系统的子菜单或子项。

    在文件系统部分,使用箭头键导航到Btrfs 文件系统支持

  12. 在突出显示Btrfs 文件系统支持后,按 ybtrfs 支持包含在自定义内核中。完成后,在突出显示的选项旁边应该出现星号 (*)。最终屏幕应类似于这里显示的屏幕

    Kernel Configuration File Systems screen

  13. 按键盘上的 Esc 两次返回主内核配置屏幕。

  14. 再次按键盘上的 Esc 两次退出内核配置应用程序。退出内核配置器将强制将您的更改保存到内核源代码树根目录中的 .config 文件。

  15. 将出现一个对话框,提示您保存新配置。确保选择“是”,然后按 Enter

  16. 内核配置实用程序退出后,您将被抛回您的 shell——在内核源代码树中。

    提示

    要查看使用 menuconfig 工具进行的一些更改的结果,请使用 grep 实用程序直接查看您保存的 .config 文件。例如,要查看启用 btrfs 文件系统支持的效果,请键入以下内容

    # grep  ^CONFIG_BTRFS_FS  ~/build/kernel/.config
    
    CONFIG_BTRFS_FS=y
    
  17. 让我们优化内核构建时间,并减少内核编译阶段使用的磁盘空间量。通过设置 CONFIG_DEBUG_INFO=no,生成的内核映像将不包含调试信息,从而导致内核映像更小。这会从构建的内核和模块中删除调试符号。键入

    $ ./scripts/config --file ~/build/kernel/.config  -d DEBUG_INFO \
      -d DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT -d DEBUG_INFO_DWARF4  \
      -d DEBUG_INFO_DWARF5 -e CONFIG_DEBUG_INFO_NONE
    
  18. 完成 Rocky Linux 发行版上自定义内核的另一个重要步骤。键入

    sed -ri '/CONFIG_SYSTEM_TRUSTED_KEYS/s/=.+/=""/g' ~/build/kernel/.config 
    
  19. 向新内核添加一个简单的自定义项,以便您可以更容易地将其与其他库存内核区分开来。为此,请使用 sed 实用程序就地编辑 Makefile。键入

    sed  -i 's/^EXTRAVERSION.*/EXTRAVERSION = -custom/'  Makefile
    
  20. 通过将 kernelversion 目标传递给 make 命令来验证您刚刚自定义的内核的完整版本。键入

    make O=~/build/kernel kernelversion
    

    输出

    make[1]: Entering directory '/home/rocky/build/kernel'
    6.5.7-custom
    make[1]: Leaving directory '/home/rocky/build/kernel'
    
  21. 您已准备好编译内核。键入

    sudo make  O=~/build/kernel -j $(nproc)
    

    输出

    make[1]: Entering directory '/root/build/kernel'
    SYNC    include/config/auto.conf.cmd
    GEN     Makefile
    HOSTCC  scripts/kconfig/conf.o
    ...
    
  22. 编译成功完成后,您将最终得到存储在此处的完成内核

    ~/build/kernel/arch/x86/boot/bzImage
    
  23. 安装配置为模块的内核部分。键入

    sudo make O=~/build/kernel modules_install
    
  24. 现在已经构建了内核,是时候安装它了。键入

    sudo cp ~/build/kernel/arch/x86/boot/bzImage  \
    /boot/vmlinuz-<kernel-version>
    

    <kernel-version> 替换为您的自定义内核的版本号。对于我们在本指南中使用的示例内核,文件名将是 vmlinuz-6.*-custom。因此,以下是本示例的精确命令

    sudo cp ~/build/kernel/arch/x86/boot/bzImage  /boot/vmlinuz-6.5.7-custom
    
  25. 使用相同的命名约定将相应的 System.map 文件复制并重命名到 /boot 目录

    sudo cp -v ~/build/kernel/System.map /boot/System.map-6.5.7-custom
    
  26. 使用 kernel-install 实用程序完成文件步骤。键入

    sudo kernel-install add  6.5.7-custom /boot/vmlinuz-6.5.7-custom
    
  27. kernel-install 实用程序将在引导加载程序配置文件中创建一个新的引导条目。对于基于 EFI 的系统,您可以在 /boot/loader/entries/ 下查找匹配的条目。

  28. 运行 grubby 程序以查看服务器的默认内核。键入

    sudo grubby --default-kernel
    
  29. 一切就绪。现在是真相的时刻。最新的内核很可能被配置为新的默认内核以引导进入。如果您能够访问系统的控制台,您可以重新引导系统并在 GRUB 引导菜单中选择新的自定义内核。如果重新引导后一切顺利,您可以通过运行以下命令验证系统是否正在运行自定义内核

    uname -r
    

作者:瓦莱·索因卡

贡献者:史蒂文·斯宾塞,甘娜·吉尔诺娃