Kernel Modules Explained: lsmod, modprobe, and DKMS

Kernel Modules Explained: lsmod, modprobe, and DKMS

The Linux kernel would be unmanageably huge if every driver for every device were compiled in. Instead, nearly everything is a module: a chunk of kernel code loaded at runtime when its hardware appears and removable when it is not needed. Wi-Fi drivers, filesystem implementations, USB gadgets, the NVIDIA driver: all modules. Most of the time the machinery is invisible, which is exactly why the commands for inspecting it are worth knowing for the day it is not.

Seeing what is loaded

lsmod | head
# Module                  Size  Used by
# amdgpu              12345678  42
# btusb                  65536  0
# ext4                 1048576  1

lsmod lists loaded modules, their memory footprint, and the “Used by” column showing reference counts and dependent modules. For any module, modinfo shows what it actually is:

modinfo amdgpu | head
# description: AMD GPU
# license:     GPL and additional rights
# firmware:    amdgpu/...
# parm:        ...

The parm: lines list tunable parameters, and the currently active values are readable under /sys/module/<name>/parameters/. When a forum post tells you to set some driver option, this is the plumbing it is talking about.

Loading and unloading: modprobe

sudo modprobe btusb          # load, with dependencies
sudo modprobe -r btusb       # unload, if nothing is using it

modprobe is the correct interface: it resolves dependencies (loading a module can require half a dozen others first), consults configuration, and knows where modules live: /lib/modules/$(uname -r)/, one tree per installed kernel. The lower-level insmod/rmmod load single files with no dependency logic and are mostly useful for kernel developers.

That per-kernel-version path explains a whole category of breakage, which we will get to with DKMS.

Automatic loading, and why you rarely modprobe

You almost never load modules by hand because the kernel does it on demand: when hardware is detected, the kernel emits an event carrying the device’s ID, udev matches it to a module alias, and modprobe runs automatically. Filesystems load their modules at mount time the same way. The manual controls exist for the exceptions: forcing a module at boot regardless of detection (a line in /etc/modules-load.d/*.conf) and passing options:

# /etc/modprobe.d/audio-fix.conf
options snd-hda-intel power_save=0

Blacklisting: keeping a module out

The flip side is preventing a load: a buggy driver, or two drivers fighting over one device (the classic case being nouveau vs the NVIDIA proprietary driver). A file in /etc/modprobe.d/:

# /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
install nouveau /bin/false

blacklist stops automatic loading by alias; the install ... /bin/false line is the belt-and-suspenders form that defeats explicit and dependency loads too. One more step matters: modules needed early in boot are loaded from the initramfs, which has its own copy of this configuration, so rebuild it after blacklisting (update-initramfs -u on Debian/Ubuntu, dracut --force on Fedora) or the blacklist will mysteriously not apply.

DKMS: surviving kernel updates

Modules are compiled against one specific kernel version. In-tree drivers ship inside every kernel package, so updates carry them along automatically. Out-of-tree drivers, NVIDIA’s proprietary driver, VirtualBox’s kernel glue, some Wi-Fi vendor drivers, are built separately, and a kernel update would silently leave them behind: new kernel boots, module for it does not exist, graphics or networking gone.

DKMS (Dynamic Kernel Module Support) closes that gap by registering the module’s source and rebuilding it automatically whenever a kernel is installed:

dkms status
# nvidia/580.65.06, 7.1.12-arch1, x86_64: installed
# nvidia/580.65.06, 7.2.1-arch1,  x86_64: installed

Distro packages named like nvidia-dkms, broadcom-sta-dkms, or virtualbox-dkms are exactly this arrangement. When a driver vanishes after an update, dkms status is the first diagnostic: a missing or “added”-but-not-”installed” entry for the new kernel means the rebuild failed (usually missing kernel headers, fixed by installing linux-headers-$(uname -r) and running dkms autoinstall).

A note on secure boot

With Secure Boot enabled, the kernel only loads signed modules. Distribution-shipped modules are signed already; DKMS-built ones are signed with a local machine owner key (MOK) that you enroll once at boot, a prompt that surprises people mid-update. If a freshly built module refuses to load with a signature error, the MOK enrollment step is what got skipped, and mokutil is the tool for it.

Frequently Asked Questions

What is a kernel module?

A piece of kernel code, most often a driver or filesystem implementation, that can be loaded into and removed from the running kernel without rebooting. Modules live under /lib/modules for each installed kernel version.

What is the difference between insmod and modprobe?

insmod loads exactly one module file with no dependency handling. modprobe resolves and loads the module plus everything it depends on, reads configuration from /etc/modprobe.d, and is what you should use in practice.

How do I stop a module from ever loading?

Create a file in /etc/modprobe.d containing blacklist modulename, and for stubborn cases add install modulename /bin/false. Rebuild the initramfs afterward if the module loads early in boot.

What is DKMS?

Dynamic Kernel Module Support automatically rebuilds out-of-tree modules, such as NVIDIA or VirtualBox drivers, every time a new kernel is installed, so hardware keeps working across kernel updates.

Why did my driver break after a kernel update?

Modules are built per kernel version. An out-of-tree module that was not rebuilt for the new kernel simply does not exist under the new /lib/modules tree. DKMS exists to prevent exactly this, so check dkms status.

How can I see what hardware a module drives and what options it takes?

modinfo modulename shows the description, license, hardware IDs, and available parameters. Current parameter values live under /sys/module/modulename/parameters.