美文网首页open_source_unix_science
使用 DKMS 管理内核模块

使用 DKMS 管理内核模块

作者: yestyle | 来源:发表于2018-11-16 16:21 被阅读121次

    引言

    在《VPN 新宠 WireGuard 搭建》一文中提到,Ubuntu 系统上安装 WireGuard 使用如下命令:

    $ sudo add-apt-repository ppa:wireguard/wireguard
    $ sudo apt-get update
    $ sudo apt-get install wireguard
    

    实际上安装的一共有三个包:wireguardwireguard-dkmswireguard-tools,其中的 wireguard-dkms 即用于 DKMS。

    DKMS(Dynamic Kernel Module Support)是由 Dell 公司开发的一套内核模块管理框架,被大多数 Linux 发行版采用。 DKMS 在内核源码树之外做了个拷贝,每当内核更新时可自动重新编译内核模块,对于多个不同的内核版本、模块版本的管理非常便利。

    在 WireGuard 正式并入 Linux 内核主线之前,使用 DKMS 管理模块代码是最理想的选择。本文通过以 DKMS 方式从源码编译、安装 WireGuard,简单介绍 DKMS 的使用方法。

    准备工作

    前几步与 WireGuard 官网安装页面的说明相同:

    安装工具链

    安装编译 WireGuard 需要的工具链和信赖包:

    $ sudo apt-get install libmnl-dev libelf-dev linux-headers-$(uname -r) build-essential pkg-config
    

    除此之外,还需要安装 dkms 包:

    $ sudo apt-get install dkms
    

    下载源码

    克隆最新的 WireGuard 源码库到 /home/yestyle/code 目录:

    $ cd /home/yestyle/code
    $ git clone https://git.zx2c4.com/WireGuard
    

    满足 DKMS 要求

    使用 DKMS 管理内核模块,需要满足两个要求

    • 将源码放在 /usr/src/<module_name>-<module_version> 目录下;
    • 在源码根目录下存在合法的 dkms.conf 配置文件。

    第二点要求已在源码 WireGuard/src 目录下提供。对于第一点要求,WireGuard/src/Makefile 中的 dkms-install 目标可用于此目的:

    $ cd WireGuard/src
    $ sudo make dkms-install
    

    此命令将使用源码版本信息更新 version.hdkms.conf,同时将更新后的源码目录拷贝到 /usr/src/wireguard 中。更新之后的 dkms.conf 类似这样:

    PACKAGE_NAME="wireguard"
    PACKAGE_VERSION="0.0.20181115-1-gab873cd"
    AUTOINSTALL=yes
    
    BUILT_MODULE_NAME="wireguard"
    DEST_MODULE_LOCATION="/kernel/net"
    
    # requires kernel 3.10 or greater:
    BUILD_EXCLUSIVE_KERNEL="^(([^1230]\.)|(3\.1[0-9]))"
    

    注意其中的 PACKAGE_VERSION 的值,在后面会使用到。

    另外,由 WireGuard/src/Makefile 可知,更新 dkms.conf 文件的内容时,会使用 git update-index --assume-unchanged dkms.conf 更新 dkms.conf 文件的 Git 索引,因此 git status 看不到 dkms.conf 有修改,version.h 类似。

    之后,DKMS 就可以派上用场啦。

    玩转 DKMS

    上述 make dkms-install 时生成的目录 /usr/src/wireguard 并不带版本号,因此使用 dkms add 时也不带版本号:

    $ cd /usr/src
    $ sudo dkms add wireguard
    
    Creating symlink /var/lib/dkms/wireguard/0.0.20181115-1-gab873cd/source ->
                     /usr/src/wireguard-0.0.20181115-1-gab873cd
    
    DKMS: add completed.
    $ dkms status
    wireguard, 0.0.20181115-1-gab873cd: added
    

    DKMS 将读取 wireguard/dkms.conf 中的版本信息,并将源码再次拷贝到 /usr/src/wireguard-0.0.20181115-1-gab873cd 目录。

    dkms build 用于编译特定版本的源码:

    $ sudo dkms build wireguard/0.0.20181115-1-gab873cd
    
    Kernel preparation unnecessary for this kernel.  Skipping...
    
    Building module:
    cleaning build area...
    make -j4 KERNELRELEASE=4.18.0-10-generic -C /lib/modules/4.18.0-10-generic/build M=/var/lib/dkms/wireguard/0.0.20181115-1-gab873cd/build......
    cleaning build area...
    
    DKMS: build completed.
    $ dkms status
    wireguard, 0.0.20181115-1-gab873cd, 4.18.0-10-generic, x86_64: built
    

    安装则使用 dkms install 命令:

    $ sudo dkms install wireguard/0.0.20181115-1-gab873cd
    
    wireguard:
    Running module version sanity check.
     - Original module
       - No original module exists within this kernel
     - Installation
       - Installing to /lib/modules/4.18.0-10-generic/updates/dkms/
    
    depmod...
    
    DKMS: install completed.
    $ dkms status
    wireguard, 0.0.20181115-1-gab873cd, 4.18.0-10-generic, x86_64: installed
    

    此后可使用 locate 命令看到 wireguard.ko 拷贝到了两个目录下:

    $ sudo updatedb
    $ locate wireguard.ko
    /lib/modules/4.18.0-10-generic/updates/dkms/wireguard.ko
    /var/lib/dkms/wireguard/0.0.20181115-1-gab873cd/4.18.0-10-generic/x86_64/module/wireguard.ko
    

    之所以有两个拷贝,是因为所有 dkms build 的版本都会拷贝到对应的 /var/lib/dkms/<module_name>/<module_version>/<kernel_version>/<arch>/module/ 目录下,而只有 dkms install 的版本会拷贝到当前运行内核对应的 /lib/modules/<kernel_version>/updates/dkms/ 目录。

    假如此时 WireGuard 源码更新了,使用 git pull 获取到最新代码后,重复上述 DKMS 的各个步骤(省略部分命令输出):

    $ cd /home/yestyle/code/WireGuard/src
    $ git pull
    $ sudo make dkms-install
    $ cd /usr/src/
    $ sudo dkms add wireguard
    $ dkms status
    wireguard, 0.0.20181115-1-gab873cd, 4.18.0-10-generic, x86_64: installed
    wireguard, 0.0.20181115-5-ge2b2f34: added
    $ sudo dkms build wireguard/0.0.20181115-5-ge2b2f34
    $ sudo dkms install wireguard/0.0.20181115-5-ge2b2f34
    $ dkms status
    wireguard, 0.0.20181115-1-gab873cd, 4.18.0-10-generic, x86_64: built
    wireguard, 0.0.20181115-5-ge2b2f34, 4.18.0-10-generic, x86_64: installed
    

    最后一步执行 dkms status 中看到之前版本的状态回退到 built,而最新安装的版本状态变为 installed。

    将已安装的新版本模块使用 dkms uninstall 卸载:

    $ sudo dkms uninstall wireguard/0.0.20181115-5-ge2b2f34
    $ dkms status
    wireguard, 0.0.20181115-1-gab873cd, 4.18.0-10-generic, x86_64: built
    wireguard, 0.0.20181115-5-ge2b2f34, 4.18.0-10-generic, x86_64: built
    

    不再需要的旧版本模块可使用 dkms remove 移除:

    $ sudo dkms remove wireguard/0.0.20181115-1-gab873cd --all
    $ dkms status
    wireguard, 0.0.20181115-5-ge2b2f34, 4.18.0-10-generic, x86_64: built
    

    另有 mkrpmmkdeb 等命令可用于制作对应的软件包。例如:

    $ sudo dkms mkdeb wireguard/0.0.20181115-5-ge2b2f34
    ...
    DKMS: mkdeb completed.
    Moving built files to /var/lib/dkms/wireguard/0.0.20181115-5-ge2b2f34/deb...
    Cleaning up temporary files...
    $ ls -l /var/lib/dkms/wireguard/0.0.20181115-5-ge2b2f34/deb
    total 352
    -rw-r--r-- 1 root root 356380 Nov 16 15:02 wireguard-dkms_0.0.20181115-5-ge2b2f34_amd64.deb
    

    需要特别说明的是,DKMS 仅可用于内核模块代码的管理,WireGuard 使用的 wgwg-quick 属于用户态的工具(wireguard-tools 包的内容),可使用如下命令编译安装:

    $ cd /home/yestyle/code/WireGuard/src/tools/
    $ make
    $ sudo make install
    

    以上。

    相关文章

      网友评论

        本文标题:使用 DKMS 管理内核模块

        本文链接:https://www.haomeiwen.com/subject/jrumfqtx.html