Difference between revisions of "Dynamic Kernel Module Support"

From ArchWiki
Jump to: navigation, search
(Simplify workaround)
(The dkms pacman hook makes the .install file obsolete)
 
(62 intermediate revisions by 22 users not shown)
Line 1: Line 1:
 
[[Category:Kernel]]
 
[[Category:Kernel]]
[[Wikipedia:Dynamic_Kernel_Module_Support|Dynamic Kernel Module Support]] allows one to compile and install kernel modules without recompiling the entire kernel.
+
[[ja:Dynamic Kernel Module Support]]
 +
[[ru:Dynamic Kernel Module Support]]
 +
[[zh-cn:Dynamic Kernel Module Support]]
 +
From [[wikipedia:Dynamic_Kernel_Module_Support|Wikipedia]]:
 +
 
 +
: '''Dynamic Kernel Module Support''' ('''DKMS''') is a program/framework that enables generating Linux kernel modules whose sources generally reside outside the kernel source tree. The concept is to have DKMS modules automatically rebuilt when a new kernel is installed.
 +
 
 +
== Effects ==
 +
 
 +
The ''positive effect'' of using DKMS is that modules are often able to be rebuilt when the kernel is upgrading.  This means that a user does not have to wait for a company, project, or package maintainer to release a new version of the module.
 +
 
 +
The ''negative effect'' of using DKMS is that DKMS breaks the Pacman database.  The problem is that the resulting modules do not belong to the package anymore, so Pacman cannot track them.  Theoretically though, support could be added through hooks (see: {{Bug|2985}}).
  
 
== Installation ==
 
== Installation ==
  
Install package {{pkg|dkms}} in the [[Official Repositories]].
+
[[Install]] the {{Pkg|dkms}} package and the headers for your kernel (for the standard kernel this would be {{Pkg|linux-headers}}).
  
After installing the DKMS, you still need to install a DKMS package such as
+
A good number of modules that lie outside the kernel source tree have a DKMS variant; a few are hosted in the [https://www.archlinux.org/packages/?&q=dkms official repositories], most are found in the [https://aur.archlinux.org/packages/?SeB=n&K=dkms AUR].  Listed below are a few of the software packages that have a DKMS variant with additional links to dedicated sections where available:
{{pkg|dkms-nvidia}}, otherwise having DKMS installed is just wasting your
+
disk space.
+
  
== Configuration ==
+
* [[AMD Catalyst]]: {{AUR|catalyst-dkms}}
 +
* [[NVIDIA]]:
 +
** {{Pkg|nvidia-dkms}}
 +
** {{Pkg|nvidia-304xx-dkms}}
 +
** {{AUR|nvidia-173xx-dkms}}
 +
** {{AUR|nvidia-96xx-dkms}}
 +
** {{AUR|nvidia-grsec-dkms}}
 +
* [[VirtualBox]], section [[VirtualBox#Hosts running a custom kernel]]
 +
* [[VMware]], section [[VMware#Using DKMS to manage the modules]]
  
To get modules get rebuilt automatically after a kernel upgrade, enable the
+
== Upgrades ==
{{ic|dkms}} service. This service will build DKMS modules if they were not
+
already available and then exit. For systemd:
+
{{bc|# systemctl enable dkms.service}}
+
  
Sometimes, a program depends on the module. If that program is started before
+
Though modules are able to be rebuilt usually through a good number of kernel upgrades, at times the package will need to get upgraded. To deal with changes in the kernel, fix bugs, or add necessary features consider upgrading the DKMS package before rebooting.
the DKMS module is built, you often need to reboot (or restart that program).
+
An example are the proprietary graphics drivers such as nvidia and catalyst.
+
  
 
== Usage ==
 
== Usage ==
If you have just upgraded your kernel and want to avoid a reboot, you can
 
trigger a rebuild for all modules by executing {{ic|dkms autoinstall -k NEW_KERNEL_VERSION}} as
 
root. This will build and install DKMS modules for all available kernel
 
versions if they have not been built before.
 
  
Forcing a build of a specific module for a specific kernel version is also
+
Usage for invoking DKMS manually.
possible, for example:
+
{{bc|# dkms install -m nvidia -v 304.51 -k 3.6.2-1-ARCH}}
+
Hint: use tab completion to get the module and kernel version.
+
  
==Guidelines==
+
Tab-completion is available by doing:
Here are some guidelines to follow.
+
  
===Package name===
+
# source /usr/share/bash-completion/completions/dkms
Since it is likely that the DKMS package duplicates a non-DKMS package, I am prefixing the DKMS-enabled package with "dkms-".
+
If I were to package something that didn't have a non-DKMS counterpart, I would still use the "dkms-" prefix.
+
  
===Where should source go?===
+
=== List modules ===
DKMS by default uses ''/usr/src/'', but [namcap] complains that is a non-standard directory. (Even though the FHS reference namcap uses states that ''/usr/src'' is "optional".
+
One could place the source in ''/opt/<package>'' and then sym-link it (which is what some non-DKMS packages do.)
+
  
Sources should go into ''/usr/src/<package>-<package version>'' which is
+
To list the current status of modules, versions and kernels within the tree:
the default directory that DKMS commands use. ''<package>'' is the "true package
+
name" (which is usually the PKGBUILD $_pkgname variable, which is the $pkgname
+
minus the "dkms-" prefix).
+
''<package version>'' refers to the ''PACKAGE_VERSION'' field in dkms.conf.
+
By convention, PKGBUILDs ''$pkgver'' should have the same value.
+
  
===Where should patches be applied?===
+
$ dkms status
One could patch the source either in the PKGBUILD or through DKMS.
+
Since non-DKMS packages patch from the PKGBUILD, and to keep the DKMS PKGBUILD as close to the non-DKMS version, I am patching in the PKGBUILD.
+
  
===Should the .install file attempt to modprobe/rmmod the module?===
+
=== Rebuild modules ===
No, it should not. Consider a module that crashes when loaded. That could halt a
+
pacman upgrade or installation which has more severe consequences.
+
  
Loading/ removing modules is a task for the user.
+
Rebuild all modules for the currently running kernel:
  
===How to create .install / dkms.conf files?===
+
# dkms autoinstall
Try to avoid updating things like version numbers in multiple files.
+
Try to avoid cluttering up PKGBUILDs/.install files with DKMS-specific stuff. (This keeps them closer to the non-DKMS files).
+
  
I've just started using a simple bash script to create the ''dkms.conf'' file and to replace text in an ''install.template'' file. This leads to much cleaner and easier to understand files.
+
or for a specific kernel:
  
You should ''not'' run {{ic|depmod}} in your .install script, this is done automatically by {{ic|dkms install}}. Running {{ic|dkms install}} depends on {{ic|dkms build}} which depends on {{ic|dkms add}} and are executed automatically. Thus, you only need to put the sources in {{ic|/usr/src/MODULE-VERSION}} and run {{ic|dkms install}} in your .install script.
+
# dkms autoinstall -k 3.16.4-1-ARCH
  
Example for a module put in {{ic|/usr/src/MODULE-VERSION}} (substitute {{ic|MODULE}} and {{ic|PACKAGE_NAME}} accordingly):
+
To build a ''specific'' module for the currently running kernel:
{{bc|<nowiki>post_install() {
+
 
    dkms install -m MODULE -v ${1%%-*}
+
# dkms install -m nvidia -v 334.21
 +
 
 +
or simply:
 +
 
 +
# dkms install nvidia/334.21
 +
 
 +
To build a module for ''all'' kernels:
 +
 
 +
# dkms install nvidia/334.21 --all
 +
 
 +
=== Remove modules ===
 +
 
 +
To remove a module (old ones are not automatically removed):
 +
 
 +
# dkms remove -m nvidia -v 331.49 --all
 +
 
 +
or simply:
 +
 
 +
# dkms remove nvidia/331.49 --all
 +
 
 +
If the package {{Pkg|dkms}} is removed the information regarding previous module build files is lost. If this is the case, go through {{ic|/usr/lib/modules/KERNELVERSION-ARCH}} and delete or files and directories no longer in use.
 +
 
 +
== DKMS package creation ==
 +
 
 +
Here are some guidelines to follow when creating a DKMS package.
 +
 
 +
=== Package name ===
 +
 
 +
DKMS packages are named by appending "''-dkms''" to the original package name.
 +
 
 +
The variable {{ic|$_pkgname}} is often used below {{ic|$pkgname}} to describe the package name minus the "''-dkms''" suffix (e.g. {{ic|<nowiki>_pkgname=${pkgname%-*}</nowiki>}}). This is useful to help keep similarities between the original package PKGBUILD and the DKMS variant.
 +
 
 +
=== Dependencies ===
 +
 
 +
Dependencies should be inherited from the original version with {{Pkg|dkms}} added and {{Pkg|linux-headers}} removed (as it is listed by the dkms package as ''optional'').
 +
 
 +
=== Build source location ===
 +
 
 +
Build sources should go into (this is the default build directory for DKMS):
 +
 
 +
/usr/src/''PACKAGE_NAME''-''PACKAGE_VERSION''
 +
 
 +
In the package directory, a DKMS configuration tells DKMS how to build the module ({{ic|dkms.conf}}), including the variables {{ic|PACKAGE_NAME}} and {{ic|PACKAGE_VERSION}}.
 +
 
 +
* {{ic|PACKAGE_NAME}} - the actual project name (usually {{ic|$_pkgname}} or {{ic|$_pkgbase}}).
 +
* {{ic|PACKAGE_VERSION}} - by convention this should also be the {{ic|$pkgver}}.
 +
 
 +
=== Patching ===
 +
 
 +
The sources can be patched either directly in the PKGBUILD or through {{ic|dkms.conf}}.
 +
 
 +
=== Module loading automatically in .install ===
 +
 
 +
Loading and unloading modules should be left to the user.  Consider the possibility a module may crash when loaded.
 +
 
 +
=== namcap output ===
 +
 
 +
[[namcap]] (which attempts to check for common mistakes and non-standard decisions in a package) is good practice to use at least once on ''any'' package; however, it has not yet been updated for DKMS specific guidelines.
 +
 
 +
For example, DKMS uses {{ic|/usr/src/}} by default, but Namcap believes this to be a non-standard directory, a little contrary to its [[Wikipedia:Filesystem Hierarchy Standard|reference]].
 +
 
 +
=== Example ===
 +
 
 +
Here is an example package that edits {{ic|dkms.conf}} according to the package name and version.
 +
 
 +
==== PKGBUILD ====
 +
 
 +
{{hc|PKGBUILD|2=
 +
# 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 <nowiki>'</nowiki>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 ====
 +
 +
{{hc|dkms.conf|2=
 +
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 ====
 +
 +
{{Accuracy|Those actions where moved to pacman hooks AFAIK.}}
 +
 +
Instead of {{ic|depmod}} now {{ic|dkms install}} can be used (it depends on {{ic|dkms build}}, which depends on {{ic|dkms add}}):
 +
 +
{{hc|amazing-dkms.install|
 +
# old version (without -$pkgrel): ${1%%-*}
 +
# new version (without -$pkgrel): ${2%%-*}
 +
 +
post_install() {
 +
    dkms install ''amazing''/${1%%-*}
 +
}
 +
 
pre_upgrade() {
 
pre_upgrade() {
     local curver=${2%%-*}
+
     pre_remove ${2%%-*}
    # $2 is unset due to a bug. See, https://bugs.archlinux.org/task/32278
+
    # Query current version using pacman as fallback
+
    [ -n "$curver" ] || curver=$(pacman -Q PACKAGE_NAME | cut -d' ' -f2)
+
    pre_remove $curver
+
 
}
 
}
 +
 
post_upgrade() {
 
post_upgrade() {
 
     post_install ${1%%-*}
 
     post_install ${1%%-*}
 
}
 
}
pre_remove() {
 
    dkms remove -m MODULE -v ${1%%-*} --all
 
}</nowiki>}}
 
  
===DKMS breaks the ABS===
+
pre_remove() {
Sort of, yes. The problem is that the resulting modules don't belong to the package, so pacman can't track or report on them.
+
    dkms remove ''amazing''/${1%%-*} --all
 
+
}
I don't think that's a show-stopper, but it probably puts DKMS out on the fringe a bit.
+
}}
There is some talk about pacman adding similar support through pacman hooks. [https://wiki.archlinux.org/index.php/User:Allan/Pacman_Hooks].
+
I think you could "fake" the ownership, by installing the module as normal (or even a "dummy" file) and just letting DKMS overwrite it.
+
  
===namcap issues===
+
{{Tip|To keep DKMS packages closer to their non-DKMS counterparts: avoid cluttering up package files with DKMS-specific stuff (e.g. version numbers that need updating).}}
As mentioned earlier, namcap complains if you put source in ''/usr/src''.
+
Also, namcap can not detect that dkms is a dependency. (I guess maybe it's not technically a dependency, but...)
+
  
Basically, take the dependencies of the non-DKMS version, add 'dkms' and remove 'linux-headers' (since dkms optdepends on that)
+
== See also ==
  
==See Also==
+
* [http://www.linuxjournal.com/article/6896 Linux Journal: Exploring Dynamic Kernel Module Support]
*[http://linux.dell.com/dkms/manpage.html Dell's DKMS man page] Official site.
+
*[http://manpages.ubuntu.com/manpages/karmic/man8/dkms.8.html Ubuntu's DKMS man page] (Documents some officially un-documented bits.)
+
*[http://www.linuxjournal.com/article/6896 Exploring Dynamic Kernel Module Support]
+

Latest revision as of 15:47, 11 May 2016

From Wikipedia:

Dynamic Kernel Module Support (DKMS) is a program/framework that enables generating Linux kernel modules whose sources generally reside outside the kernel source tree. The concept is to have DKMS modules automatically rebuilt when a new kernel is installed.

Effects

The positive effect of using DKMS is that modules are often able to be rebuilt when the kernel is upgrading. This means that a user does not have to wait for a company, project, or package maintainer to release a new version of the module.

The negative effect of using DKMS is that DKMS breaks the Pacman database. The problem is that the resulting modules do not belong to the package anymore, so Pacman cannot track them. Theoretically though, support could be added through hooks (see: FS#2985).

Installation

Install the dkms package and the headers for your kernel (for the standard kernel this would be linux-headers).

A good number of modules that lie outside the kernel source tree have a DKMS variant; a few are hosted in the official repositories, most are found in the AUR. Listed below are a few of the software packages that have a DKMS variant with additional links to dedicated sections where available:

Upgrades

Though modules are able to be rebuilt usually through a good number of kernel upgrades, at times the package will need to get upgraded. To deal with changes in the kernel, fix bugs, or add necessary features consider upgrading the DKMS package before rebooting.

Usage

Usage for invoking DKMS manually.

Tab-completion is available by doing:

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

List modules

To list the current status of modules, versions and kernels within the tree:

$ dkms status

Rebuild modules

Rebuild all modules for the currently running kernel:

# dkms autoinstall

or for a specific kernel:

# dkms autoinstall -k 3.16.4-1-ARCH

To build a specific module for the currently running kernel:

# dkms install -m nvidia -v 334.21

or simply:

# dkms install nvidia/334.21

To build a module for all kernels:

# dkms install nvidia/334.21 --all

Remove modules

To remove a module (old ones are not automatically removed):

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

or simply:

# dkms remove nvidia/331.49 --all

If the package dkms is removed the information regarding previous module build files is lost. If this is the case, go through /usr/lib/modules/KERNELVERSION-ARCH and delete or files and directories no longer in use.

DKMS package creation

Here are some guidelines to follow when creating a DKMS package.

Package name

DKMS packages are named by appending "-dkms" to the original package name.

The variable $_pkgname is often used below $pkgname to describe the package name minus the "-dkms" suffix (e.g. _pkgname=${pkgname%-*}). This is useful to help keep similarities between the original package PKGBUILD and the DKMS variant.

Dependencies

Dependencies should be inherited from the original version with dkms added and linux-headers removed (as it is listed by the dkms package as optional).

Build source location

Build sources should go into (this is the default build directory for DKMS):

/usr/src/PACKAGE_NAME-PACKAGE_VERSION

In the package directory, a DKMS configuration tells DKMS how to build the module (dkms.conf), including the variables PACKAGE_NAME and PACKAGE_VERSION.

  • PACKAGE_NAME - the actual project name (usually $_pkgname or $_pkgbase).
  • PACKAGE_VERSION - by convention this should also be the $pkgver.

Patching

The sources can be patched either directly in the PKGBUILD or through dkms.conf.

Module loading automatically in .install

Loading and unloading modules should be left to the user. Consider the possibility a module may crash when loaded.

namcap output

namcap (which attempts to check for common mistakes and non-standard decisions in a package) is good practice to use at least once on any package; however, it has not yet been updated for DKMS specific guidelines.

For example, DKMS uses /usr/src/ by default, but Namcap believes this to be a non-standard directory, a little contrary to its reference.

Example

Here is an example package that edits dkms.conf according to the package name and version.

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

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: Those actions where moved to pacman hooks AFAIK. (Discuss in Talk:Dynamic Kernel Module Support#)

Instead of depmod now dkms install can be used (it depends on dkms build, which depends on 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: To keep DKMS packages closer to their non-DKMS counterparts: avoid cluttering up package files with DKMS-specific stuff (e.g. version numbers that need updating).

See also