Linux之DKMS详解

背景

上一篇简单介绍了下DKMS:https://z-dd.online/2024/08/30/Linux%E4%B9%8BDKMS/
这篇详细介绍下整个DKMS相关的文件及流程。

DKMS相关文件

相关文件及路径:

  • /etc/dkms目录

    • /etc/dkms/template-dkms-mkbmdeb: 二进制deb包配置模板,用于创建DKMS模块的二进制deb包,用户可自定义该配置,方式同下。
    • /etc/dkms/template-dkms-mkdeb: deb包配置模板,用于创建DKMS模块的deb包,可被用户代码目录下自定义的模板配置取代:/usr/src/<module>-<module-version>/<module>-dkms-mkdeb
    • /etc/dkms/template-dkms-mkdsc: 源码deb包配置模板,与上面一个的脚本内容一致,创建的符号链接指向template-dkms-mkdeb,
    • /etc/dkms/framework.conf: DKMS框架通用的配置文件,可以修改一些默认配置。
  • /etc/kernel/目录

    • /etc/kernel/header_postinst.d/dkms:后面会详细说明该文件。
    • /etc/kernel/postinst.d/dkms:与上面一个的脚本内容一致,内核包安装或更新过程中执行。
    • /etc/kernel/prerm.d/dkms:在内核包被卸载之前执行,主要进行一些清理工作,比如dkms remove操作,rmdir /lib/modules/$inst_kern/updates等。
  • /etc/modprobe.d/dkms.conf: 默认没有什么内容,用于DKMS模块的modprobe信息。

  • /usr/lib/dkms目录

    • /usr/lib/dkms/dkms-autopkgtest
    • /usr/lib/dkms/dkms_autoinstaller:自动编译更新内核模式时调用该脚本,里面主要调用dkms autoinstall命令来更新 DKMS 模块
    • /usr/lib/dkms/common.postinst:后面会详细说明该文件。
  • /usr/sbin/dkms:dkms命令行工具,用于安装、构建和卸载 DKMS 模块,是个脚本,可直接查看。

下面来看看几个比较重要的文件:

/etc/kernel/header_postinst.d/dkms: 安装或更新 Linux 内核头文件后运行,主要工作是检查内核头文件,并调用/usr/lib/dkms/dkms_autoinstaller来更新 DKMS 模块

#!/bin/bash

# We're passed the version of the kernel being installed
inst_kern=$1

uname_s=$(uname -s)

_get_kernel_dir() {
    KVER=$1
    case ${uname_s} in
       Linux)          DIR="/lib/modules/$KVER/build" ;;
       GNU/kFreeBSD)   DIR="/usr/src/kfreebsd-headers-$KVER/sys" ;;
    esac
    echo $DIR
}

_check_kernel_dir() {
    DIR=$(_get_kernel_dir $1)
    case ${uname_s} in
       Linux)          test -e $DIR/include ;;
       GNU/kFreeBSD)   test -e $DIR/kern && test -e $DIR/conf/kmod.mk ;;
       *)              return 1 ;;
    esac
    return $?
}

case "${uname_s}" in
    Linux)
        header_pkg="linux-headers-$inst_kern"
        kernel="Linux"
    ;;
    GNU/kFreeBSD)
        header_pkg="kfreebsd-headers-$inst_kern"
        kernel="kFreeBSD"
    ;;
esac

if [ -x /usr/lib/dkms/dkms_autoinstaller ]; then
    exec /usr/lib/dkms/dkms_autoinstaller start $inst_kern
fi

if ! _check_kernel_dir $inst_kern ; then
    echo "dkms: WARNING: $kernel headers are missing, which may explain the above failures." >&2
    echo "      please install the $header_pkg package to fix this." >&2
fi

/usr/lib/dkms/common.postinst: dkms的通用编译安装脚本,这个脚本内容比较多,这里就不贴出来了,感兴趣的同学可以自行去研究。里面主要做了以下事情:检查内核及内核版本;使用dkms remove移除旧的dkms模块;编译并安装新的dkms模块(dkms adddkms builddkms install);

流程:

下面看看dkms的一些主要流程。

deb包编译安装流程

安装deb包时调用deb包的postinst
-> /etc/dkms/template-dkms-mkdeb/debian/postinst默认模板脚本 或者 自定义的/usr/src/<module>-<module-version>/<module>-dkms-mkdeb
-> 调用编译安装脚本:/usr/lib/dkms/common.postinst通用脚本 或者 自定义的 /usr/share/$PACKAGE_NAME/postinst
-> 调用dkms adddkms builddkms install等系列操作编译安装dkms模块

更新内核后自动编译流程

更新内核或是内核头文件时
-> 触发执行/etc/kernel/postinst.d/dkms或是/etc/kernel/header_postinst.d/dkms(内容一样,前面有说明)
-> 调用/usr/lib/dkms/dkms_autoinstaller
-> 调用dkms autoinstall命令来更新 DKMS 模块

参考

  • manual dkms 及相关脚本代码