使用 DKMS 添加内核模块

本指南介绍如何使用 DKMS 添加内核模块。

概述

某些内核模块在 Clear Linux* OS 中默认启用。要使用不属于 Linux 源代码树的其他内核模块,您可能需要构建树外内核模块。按照本指南使用 DKMS 添加内核模块,或参阅 手动添加内核模块

描述

内核模块是能够插入到 Linux 内核中以增加功能的附加软件,例如硬件驱动程序。内核模块可能已经是 Linux 源代码树的一部分(树内),也可能来自外部来源,例如直接来自供应商(树外)。

DKMS 是一个便于构建和安装内核模块的框架。DKMS 允许 Clear Linux OS 提供钩子,为新版本内核自动重新构建模块。

内核模块可用性

Clear Linux OS 附带了许多上游内核模块以备使用。使用现有模块时,维护和保留 Clear Linux OS 内核的签名验证要容易得多。有关 Clear Linux OS 安全实践的更多信息,请参阅 操作系统安全性 页面。

继续之前,请检查您正在寻找的内核模块是否已经在 Clear Linux OS 中可用,或者提交添加该模块的请求。

检查模块是否已经可用

您可以使用 swupd search 命令搜索以 .ko 文件扩展名结尾的内核模块文件名,如下例所示。有关详细信息,请参阅 swupd

sudo swupd search ${module_name}.ko

提交添加模块的请求

如果您需要的内核模块已经开源(例如在 Linux 上游),并且可能对其他人也有用,可考虑提交在 Clear Linux OS 内核中添加或启用该模块的请求。

向 GitHub 上的 Clear Linux OS ‘Distribution Project’_ 提出增强请求。

安装 DKMS

kernel-native-dkms 捆绑包提供了 dkms 程序和 Linux 内核头文件,它们是编译内核模块所必需的。

kernel-native-dkms 捆绑包还会:

  • 添加 systemd update trigger (/usr/lib/systemd/system/dkms-new-kernel.service),用来在使用 swupd update 升级内核后自动运行 DKMS 来重新构建模块。
  • 通过附加来自 /usr/share/kernel/cmdline.d/clr-ignore-mod-sig.conf 文件的内核命令行参数 (module.sig_unenforce),禁用内核模块签名验证。
  • 向每日消息 (MOTD) 添加一条通知,指示内核模块签名验证已禁用。

警告

我们建议您始终查看 swupd update 输出,确保为新内核成功重新构建了内核模块。这对引导是否成功有赖于内核模块的系统尤其重要。

安装 kernel-native-dkmskernel-lts-dkms 捆绑包:

  1. 确定 Clear Linux OS 上运行的内核变体。只有 nativelts 内核能够使用 DKMS 构建和加载树外内核模块。

    $ uname -r
    5.XX.YY-ZZZZ.native
    

    确保内核名称中含有 .native.lts

  2. 安装与已安装内核相对应的 DKMS 捆绑包。为 native 内核使用 kernel-native-dkms,或者为 lts 内核使用 kernel-lts-dkms

    sudo swupd bundle-add kernel-native-dkms
    

    或者

    sudo swupd bundle-add kernel-lts-dkms
    
  3. 更新 Clear Linux OS 引导加载程序并重启。

    sudo clr-boot-manager update
    reboot
    

构建、安装和加载树外模块

如果您是个人用户或测试人员,并且您需要 Clear Linux OS 并未提供的树外内核模块,请按照本节中的步骤操作。如需使用可扩展性和可自定义性更好的方法,我们建议使用 mixer 来提供自定义内核和更新。

必备条件

开始之前,您必须:

  • 在 UEFI/BIOS 中禁用安全引导。加载新的树外模块会修改安全引导所依赖的信任签名。
  • 获取以源代码或预编译二进制形式存在的内核模块包。

获取内核模块源代码

内核模块源代码目录中必需的 dkms.conf 文件将指示 DKMS 应该如何编译内核模块。

内核模块可以打包为:

  • 不含 dkms.conf 文件的源代码
  • 含预制作的 dkms.conf 文件的源代码
  • 含预制作的 dkms.conf 文件和预编译的模块二进制的源代码
  • 只有预编译的模块二进制(不含源代码)

在上面列出的包类型中,只有预编译的内核模块二进制文件不起作用,因为 Clear Linux OS 要求在加载内核模块之前根据同一内核源代码树进行构建。如果只能获取不含 dkms.conf 文件的源代码,则必须手动创建 dkms.conf 文件,本文档稍后将对此进行介绍。

  1. 下载内核模块的源代码。

    • 查看可用的下载选项。一些内核模块提供单独的归档文件来专门支持 DKMS。
    • 查看自述文件,因为它通常提供在支持 DKMS 的情况下构建模块所需的信息。
    curl -O http://<URL-TO-KERNEL-MODULE-SOURCE>.tar.gz
    tar -xvf <KERNEL-MODULE-SOURCE>.tar.gz
    cd <KERNEL-MODULE-SOURCE>/
    cat README
    

使用现有的 dkms.conf 构建内核模块

如果内核模块维护者使用 dkms mktarball 命令打包了源代码归档文件,则整个归档文件可以传递给 dkms ldtarball,由后者来完成许多步骤。

归档文件包含必需的 dkms.conf 文件,并可能包含 dkms_source_tree 目录和 dkms_binaries_only 目录。

  1. 对内核模块归档文件运行 dkms ldtarball 命令。

    dkms ldtarball <KERNEL-MODULE-SOURCE_WITH_DKMS>.tar.gz
    

    dkms ldtarball 会将内核模块源代码放在 /usr/src/<MODULE-NAME>-<MODULE-VERSION>/ 下,在必要时构建它,以及将模块添加到 DKMS 树。

  2. 检查 dkms status 命令的输出,确认已检测到的内核模块。

    dkms status
    
  3. 安装内核模块。

    dkms install -m <MODULE-NAME> -v <MODULE-VERSION>
    

在没有现成的 dkms.conf 的情况下构建内核模块

如果内核模块源代码中不含 dkms.conf 文件或 dkms ldtarball 命令遇到错误,则必须手动创建该文件。

查看内核模块自述文件,了解 dkms.conf 文件中需要哪些内容,包括成功构建所需的特殊变量。

以下是一些可供参考的其他资源:

  • DKMS 手册页 (man dkms) 会显示 DKMS.CONF 部分的详细语法。
  • Kernel DKMS Package 的 Ubuntu 社区 wiki 条目会显示单个包含有多个模块的示例。
  • DKMS 项目 GitHub* 存储库中的 dkms.conf file 示例文件。

注解

对于要在 Clear Linux OS 更新时自动重新编译的模块,必须在 dkms.conf 中设置 AUTOINSTALL=yes

以下说明介绍了一个通用示例:

  1. 在提取的源代码目录中创建或修改 dkms.conf 文件。

    $EDITOR dkms.conf
    
    MAKE="make -C src/ KERNELDIR=/lib/modules/${kernelver}/build"
    CLEAN="make -C src/ clean"
    BUILT_MODULE_NAME=custom_module
    BUILT_MODULE_LOCATION=src/
    PACKAGE_NAME=custom_module
    PACKAGE_VERSION=1.0
    DEST_MODULE_LOCATION=/kernel/drivers/other
    AUTOINSTALL=yes
    

    本示例中的内核模块名称为 custom_module,版本为 1.0

  2. 将内核模块源代码复制到 /usr/src/ 目录中。

    sudo mkdir /usr/src/<PACKAGE_NAME>-<PACKAGE_VERSION>
    sudo cp -Rv . /usr/src/<PACKAGE_NAME>-<PACKAGE_VERSION>
    

    注解

    <PACKAGE_NAME><PACKAGE_VERSION> 必须与 dkms.conf 文件中的条目匹配。

  3. 将内核模块添加到 DKMS 树中,以便由 DKMS 跟踪。

    sudo dkms add -m <MODULE-NAME>
    
  4. 使用 DKMS 构建内核模块。如果构建时遇到错误,您可能需要编辑 dkms.conf 文件。

    sudo dkms build -m <MODULE-NAME> -v <MODULE-VERSION>
    
  5. 使用 DKMS 安装内核模块。

    sudo dkms install -m <MODULE-NAME> -v <MODULE-VERSION>
    

加载内核模块

默认情况下,DKMS 会将模块 “in-tree” 安装在 /lib/modules 下,以便可以使用 modprobe 命令加载它们。

  1. 使用 modprobe 命令加载已安装的模块。

    sudo modprobe <MODULE-NAME>
    
  2. 验证内核模块是否已加载。

    lsmod | grep <MODULE-NAME>
    

示例

可选:指定模块选项和别名

使用 modprobe 命令加载模块并设置选项。

modprobe 可能会因为模块相互依赖关系添加或移除多个模块。您可以使用 /etc/modprobe.d 目录下的配置文件来指定各个模块要使用的选项。

sudo mkdir /etc/modprobe.d

/etc/modprobe.d 目录下以 .conf 扩展名结尾的所有文件会指定加载时要使用的模块选项。您可以使用 .conf 文件为模块创建方便使用的别名,或者为有特殊要求的模块完全覆盖正常的加载行为。

参阅 modprobe.d 手册页详细了解 modprobe

man modprobe.d

可选:配置引导时要加载的内核模块

使用 /etc/modules-load.d 配置目录指定引导时自动加载的内核模块。

sudo mkdir /etc/modules-load.d

/etc/modules-load.d 目录下以 .conf 扩展名结尾的所有文件包含引导时要加载的模块别名列表(每行一个)。

参阅 modules-load.d 手册页详细了解模块加载:

man modules-load.d