Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DeelerDev/linux/llms.txt

Use this file to discover all available pages before exploring further.

Kernel modules are object files (.ko) that extend the kernel’s functionality without requiring a recompile or reboot. Drivers for hardware, network protocols, and filesystem types are common examples. When the kernel encounters hardware that needs a driver, or when userspace mounts a filesystem, the kernel can load the required module on demand using the modprobe infrastructure.

Built-in vs. modules

When you configure the kernel, each feature can be set to y (built-in), m (module), or n (disabled). Built-in code is always present in the kernel image and has zero load overhead. Modules are compiled into separate .ko files under /lib/modules/<kernel-version>/ and are loaded as needed. Use built-in (y) for:
  • Core subsystems that are always required (scheduler, memory management, virtual filesystem layer)
  • Security modules that must be active before userspace starts (SELinux, AppArmor)
  • Boot-critical drivers when you are not using an initramfs
Use modules (m) for:
  • Hardware drivers that may not be present on all systems
  • Network protocols needed only occasionally
  • Filesystems mounted after the root filesystem is up

Listing loaded modules

lsmod reads /proc/modules and displays all currently loaded modules along with their size and reference count:
lsmod
Example output:
Module                  Size  Used by
nvidia_drm             77824  4
nvidia_modeset       1155072  2 nvidia_drm
nvidia              56635392  84 nvidia_modeset
drm_kms_helper        311296  1 nvidia_drm
drm                   622592  6 drm_kms_helper,nvidia_drm
The Used by column shows which other modules depend on a given module. A module with a non-zero Used by count cannot be removed until its dependents are removed first.

Loading modules

modprobe is the standard tool for loading modules. It reads dependency information from /lib/modules/<version>/modules.dep and automatically loads any prerequisites:
# Load a module
sudo modprobe <module_name>

# Load with parameters
sudo modprobe e1000e InterruptThrottleRate=3000,3000

# Dry run: show what would be loaded without loading it
sudo modprobe --dry-run <module_name>

insmod (low-level)

insmod loads a .ko file directly from a path. Unlike modprobe, it does not resolve dependencies automatically:
sudo insmod /path/to/module.ko
sudo insmod /path/to/module.ko param=value
Prefer modprobe over insmod for normal use. insmod is mainly useful when testing a module you just compiled before installing it.

Removing modules

modprobe -r

modprobe -r removes a module and any modules it loaded that are no longer needed:
sudo modprobe -r <module_name>

rmmod

rmmod removes a single module by name. It will fail if other modules depend on it or if the module’s reference count is greater than zero:
sudo rmmod <module_name>

# Force removal even if in use (dangerous, may crash the kernel)
sudo rmmod --force <module_name>
Forcing module removal with --force can destabilize or crash the kernel. Only use it on isolated systems during development.

Inspecting module information

modinfo shows metadata embedded in a .ko file:
modinfo e1000e
Example output:
filename:       /lib/modules/6.8.0/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
description:    Intel(R) PRO/1000 Network Driver
author:         Intel Corporation, <linux.nics@intel.com>
license:        GPL v2
version:        3.2.6-k
parm:           InterruptThrottleRate:Maximum interrupts per second, per vector, (max 100000), ...
parm:           copybreak:Maximum size of packet that is copied to a new buffer on receive (uint)
The parm lines list configurable module parameters with their types and descriptions.

Module parameters

Parameters let you configure a module’s behavior when loading it. They can be passed on the modprobe command line or set permanently in a configuration file.

Passing parameters at load time

# Load with parameters on the command line
sudo modprobe usbcore blinkenlights=1

# For modules built into the kernel, pass parameters on the kernel command line
# (in /etc/default/grub or equivalent)
usbcore.blinkenlights=1

Setting parameters permanently

Create a file under /etc/modprobe.d/ with an options directive:
# /etc/modprobe.d/e1000e.conf
options e1000e InterruptThrottleRate=3000,3000 SmartPowerDownEnable=1
Any options line in /etc/modprobe.d/*.conf is applied automatically whenever the named module is loaded.

Viewing parameters at runtime

After a module is loaded, its parameters appear as files under /sys/module/<name>/parameters/:
ls /sys/module/e1000e/parameters/
cat /sys/module/e1000e/parameters/InterruptThrottleRate
Some parameters are writable and can be changed without reloading the module:
echo 5000 > /sys/module/e1000e/parameters/InterruptThrottleRate

Automatic loading at boot

/etc/modules-load.d/

To load a module at every boot, create a .conf file in /etc/modules-load.d/ containing the module name:
# /etc/modules-load.d/my-modules.conf
vfio
vfio_pci
vfio_virqfd
systemd-modules-load.service processes these files during early boot before most services start.

Aliases and automatic loading

The kernel uses aliases in /lib/modules/<version>/modules.alias to map hardware IDs to module names. When the kernel detects hardware (via PCI, USB, or other buses), it generates a modalias string and passes it to udevd, which calls modprobe automatically. You can check what module a device needs:
cat /sys/bus/pci/devices/0000:02:00.0/modalias
# outputs: pci:v00008086d000015BDsv...
modprobe $(cat /sys/bus/pci/devices/0000:02:00.0/modalias)

Module signing for Secure Boot

Systems with Secure Boot enforce that only signed kernel modules can load. The kernel option CONFIG_MODULE_SIG enables signature verification; CONFIG_MODULE_SIG_FORCE makes it mandatory (unsigned modules are rejected).
1

Generate a signing key pair

openssl req -new -x509 -newkey rsa:2048 \
  -keyout signing_key.pem -out signing_cert.pem \
  -days 3650 -subj "/CN=Module Signing/" -nodes
2

Sign a module

/usr/src/linux-headers-$(uname -r)/scripts/sign-file \
  sha256 signing_key.pem signing_cert.pem mymodule.ko
3

Enroll the certificate into the MOK database

sudo mokutil --import signing_cert.pem
Then reboot and follow the MOK Manager prompts to enroll the certificate.
For distribution kernels, check your distro’s documentation. Debian, Ubuntu, and Fedora each have their own module signing workflows integrated with DKMS.

Building out-of-tree modules

Out-of-tree (external) modules are built against the headers of an installed kernel without needing the full source tree. This is how third-party drivers (GPU drivers, VirtualBox additions, DKMS packages) work.

Basic out-of-tree build

You need a Kbuild or Makefile that declares the module:
# Kbuild
obj-m := mydriver.o
mydriver-y := mydriver_main.o mydriver_hw.o
Then build against the running kernel:
make -C /lib/modules/$(uname -r)/build M=$PWD
Or, from Linux 6.13 onwards, using the -f option:
make -f /lib/modules/$(uname -r)/build/Makefile M=$PWD
To install the built module:
make -C /lib/modules/$(uname -r)/build M=$PWD modules_install
sudo depmod -a

Using DKMS

DKMS (Dynamic Kernel Module Support) automates rebuilding out-of-tree modules when the kernel is upgraded:
# Add a DKMS module (assumes dkms.conf is present in the source directory)
sudo dkms add /usr/src/mydriver-1.0/

# Build for the current kernel
sudo dkms build mydriver/1.0

# Install
sudo dkms install mydriver/1.0
When building an out-of-tree module that depends on symbols from another external module, use the KBUILD_EXTRA_SYMBOLS variable to point modpost to the other module’s Module.symvers file, so the dependency is properly tracked.

Build docs developers (and LLMs) love