# Dynamic Kernel Module Support (简体中文)

翻译状态： 本文是英文页面 Dynamic_Kernel_Module_Support 的翻译，最后翻译时间：2017-04-24，点击这里可以查看翻译后英文页面的改动。

来自 Wikipedia:

  动态内核模块支持 (DKMS) 是一个程序框架，可以编译内核代码树之外的模块。升级内核时，通过 DKMS 管理的内核模块可以被自动重新构建以适应新的内核版本。

这意味这你不再需要等待某个公司，项目组或者包维护者释出新版本的内核模块。自从 Pacman 支持 钩子 之后，内核更新时就会自动生成和安装新的软件包。

## 安装

安装 dkms 包和内核的头文件，标准内核的头文件可以用软件包 linux-headers 安装。

有许多位于内核源码树之外的内核模块都有DKMS变体;有一些位于官方软件仓库，大多数可以在AUR找到。下面列出的是一小部分有DKMS变体的软件包

- AMD Catalyst: catalyst-dkmsAUR
- NVIDIA:
  - nvidia-dkms
  - nvidia-304xx-dkms
  - nvidia-173xx-dkmsAUR
  - nvidia-96xx-dkmsAUR
  - nvidia-grsec-dkmsAUR[broken link: package not found]
- VirtualBox:
  - virtualbox-host-dkms
  - virtualbox-guest-dkms
- VMware, section VMware#Using DKMS to manage the modules[broken link: invalid section]

- VMware, section VMware#Using DKMS to manage the modules[broken link: invalid section]

## 升级

虽然在内核升级是，DKMS 的编译自动执行，但是依然有可能编译报错。所以需要特别注意 pacman 的输出。当系统需要这些模块才能启动，或者使用不在 官方软件仓库 中的内核时，需要额外注意。

## 使用方法

如何手动调用DKMS：

可以通过执行以下命令来使能使用DKMS时的Tab补全：

    # source /usr/share/bash-completion/completions/dkms

### 列出内核模块

列出当前模块的状态，版本，包括源码树内的模块：

    # dkms status

### 重新构建模块

为当前内核重新构建所有的模块：

    # dkms autoinstall -k

或者重新构建某个特定的模块：

    # dkms autoinstall -k 3.16.4-1-ARCH

为当前内核构建一个特定的模块（例如: 对于当前内核）：

    # dkms install -m nvidia -v 334.21

或者简单地：

    # dkms install nvidia/334.21

构建一个可以兼容所有内核版本的模块：

    # dkms install nvidia/334.21 --all

### 移除模块

移除一个内核模块（旧的内核模块并不会被自动移除）：

    # dkms remove -m nvidia -v 331.49 --all

或者简单的：

    # dkms remove nvidia/331.49 --all

如果你卸载了dkms包，那么以前构建内核模块使用的相关文件信息就会丢失。如果这样，去`/usr/lib/modules/KERNELVERSION-ARCH`下删除不再需要的文件和目录。

## 创建DKMS包

创建一个新的DKMS包时，可以参考下面的指导方针。

### 包名

DKMS的包的命名方式是：原始包名加"-dkms"后缀。

通常在 `$pkgname` 后面使用 `$_pkgname` 记录不包含 "-dkms" 后缀的软件包名 (例如 `_pkgname=${pkgname%-*}`). 这样可以在原始的软件包 PKGBUILD 和 DKMS 编译文件之间保持相似性。

### 依赖

依赖的包应该是原来软件包的基础上，加上 dkms， 删除 linux-headers，内核头文件已经是 dkms 的可选依赖。

### 源代码构建位置

构建模块所需源代码需要放在（这是DKMS构建模块时使用的默认目录）：

    /usr/src/PACKAGE_NAME-PACKAGE_VERSION

在软件包目录，要包含一个 `dkms.conf` 配置文件，告诉 DKMS 如何编译。这个配置文件需要包含：

- `PACKAGE_NAME` - 实际的项目名称，通常使用 `$_pkgname` 或 `$_pkgbase`.
- `PACKAGE_VERSION` - 通常使用 `$pkgver`.

### 打补丁

为内核模块源代码打补丁既可以直接在PKGBUILD中进行，也可以通过`dkms.conf`来进行。

### .install 中模块的自动加载

模块的加载和卸载必须由用户自己来执行，设想一下，某个模块可能在加载的时候崩溃。

### namcap 输出

namcap （它会试图检查一个包中的一般性错误和不符合标准的设定）在任何包中最好至少使用一次。然而，namcap至今仍然没有针对DKMS的特殊方针做更新。

例如，默认情况下,DKMS使用`/usr/src/`，不过Namcap认为这不是一个标准目录，不符合这个reference。

### 例子

这儿有个根据包名字和版本来对`dkms.conf`进行编辑的例子。

#### PKGBUILD

    PKGBUILD

    # Maintainer: foo <foo(at)gmail(dot)com>
    # Contributor: bar <bar(at)gmai(dot)com>

    _pkgbase=amazing
    pkgname=amazing-dkms
    pkgver=1
    pkgrel=1
    pkgdesc="The Amazing kernel modules (DKMS)"
    arch=('i686' 'x86_64')
    url="https://www.amazing.com/"
    license=('GPL2')
    depends=('dkms')
    conflicts=("${_pkgbase}")
    install=${pkgname}.install
    source=("${url}/files/tarball.tar.gz"
            'dkms.conf'
            'linux-3.14.patch')
    md5sums=(use 'updpkgsums')

    build() {
      cd ${_pkgbase}-${pkgver}

      # Patch
      patch -p1 -i "${srcdir}"/linux-3.14.patch

      # Build
      msg2 "Starting ./configure..."
      ./configure

      msg2 "Starting make..."
      make
    }

    package() {
      # Install
      msg2 "Starting make install..."
      make DESTDIR="${pkgdir}" install

      # Copy dkms.conf
      install -Dm644 dkms.conf "${pkgdir}"/usr/src/${_pkgbase}-${pkgver}/dkms.conf

      # Set name and version
      sed -e "s/@_PKGBASE@/${_pkgbase}/" \
          -e "s/@PKGVER@/${pkgver}/" \
          -i "${pkgdir}"/usr/src/${_pkgbase}-${pkgver}/dkms.conf

      # Copy sources (including Makefile)
      cp -r ${_pkgbase}/* "${pkgdir}"/usr/src/${_pkgbase}-${pkgver}/
    }

#### dkms.conf

    dkms.conf

    PACKAGE_NAME="@_PKGBASE@"
    PACKAGE_VERSION="@PKGVER@"
    MAKE[0]="make --uname_r=$kernelver"
    CLEAN="make clean"
    BUILT_MODULE_NAME[0]="@_PKGBASE@"
    DEST_MODULE_LOCATION[0]="/kernel/drivers/misc"
    AUTOINSTALL="yes"

#### .install

此时可以使用`dkms install`而不是`depmod`来安装内核模块（`dkms install`依赖`dkms build`，而`dkms build`依赖`dkms add`）：

    amazing-dkms.install

    # old version (without -$pkgrel): ${1%%-*}
    # new version (without -$pkgrel): ${2%%-*}

    post_install() {
        dkms install amazing/${1%%-*}
    }

    pre_upgrade() {
        pre_remove ${2%%-*}
    }

    post_upgrade() {
        post_install ${1%%-*}
    }

    pre_remove() {
        dkms remove amazing/${1%%-*} --all
    }

Tip: 为了让软件包和非 DKMS 软件包尽量一致，请避免用使用 DKMS 特有的内容，比如版本号等。

## 相关链接

- Linux Journal: 探寻动态内核模块支持

Category:

- Kernel (简体中文)

Hidden categories:

- Pages with broken package links
- Pages with broken section links