lsmod, modprobe and safely working with the running kernel
Anyone who treats kernel modules as a black box is missing one of the most useful diagnostic tools on Linux. lsmod, modinfo and modprobe show which drivers and subsystems are actually loaded, how dependencies between modules get resolved, and how to load, remove or permanently block a module without ever recompiling the kernel.
Table of contents
- 1. What kernel modules are and why they matter
- 2. lsmod: listing and understanding loaded kernel modules
- 3. modinfo: checking metadata and dependencies
- 4. modprobe: loading and unloading modules with dependency resolution
- 5. insmod and rmmod: the direct, riskier path
- 6. Loading kernel modules automatically at boot
- 7. Blacklisting modules and persisting parameters
- 8. Troubleshooting: when a kernel module refuses to load
- 9. Kernel module tools compared
- 10. Summary
- 11. FAQ
1. What kernel modules are and why they matter
A kernel module is a piece of code that can be loaded into or removed from a running Linux kernel without a reboot. Drivers for network cards, filesystem drivers such as XFS or Btrfs, firewall backends like nf_tables, or virtual devices such as the loopback device are almost always shipped as kernel modules rather than built statically into the kernel. This keeps the running kernel small in memory, since only the subsystems actually needed are loaded, and it lets distributions ship a single kernel that works across very different hardware.
For system administrators, kernel modules matter mainly because they are one of the first places to look when hardware or networking breaks. If a driver for a RAID controller card is missing, the kernel will not load the matching module automatically, and the disks stay invisible. If a kernel module is misconfigured, it can trigger kernel panics or leave network interfaces in an inconsistent state. lsmod, modinfo and modprobe together form the standard toolset for fully understanding and deliberately changing the module state of a system.
2. lsmod: listing and understanding loaded kernel modules
The lsmod command reads /proc/modules and prints a formatted table of every currently loaded kernel module with three columns: name, size in bytes, and a usage counter listing the names of modules depending on it. A module with a usage counter of 0 is loaded but no longer referenced by any other module or running process, which makes it a candidate for unloading. A usage counter above 0 means an unload attempt with rmmod will fail as long as the dependency exists.
In practice, lsmod is almost always combined with grep to search for a specific driver or subsystem, for example to check whether the kernel module for a given network card or filesystem is loaded at all. Since lsmod is just a readable formatting of /proc/modules, the same state can also be read directly with cat /proc/modules, which is useful in scripts that should not depend on lsmod itself. The output is deterministic and works well for monitoring checks that verify a security relevant module such as overlay for containers is actually active.
# List all currently loaded kernel modules
lsmod
# Typical output columns: Module, Size, Used by
# Module Size Used by
# nf_tables 172032 10 nft_ct,nft_chain_nat,...
# xt_conntrack 16384 1
# ip6table_filter 16384 1
# xfs 2072576 1
# Search for a specific driver or subsystem
lsmod | grep -i xfs
# Check whether the overlay filesystem module (used by Docker) is loaded
lsmod | grep overlay
# Same information without lsmod, straight from the proc filesystem
cat /proc/modules | column -t
# Count how many modules are currently loaded
lsmod | tail -n +2 | wc -l
3. modinfo: checking metadata and dependencies
While lsmod only shows what is currently loaded, modinfo provides detailed metadata for any kernel module, whether it is loaded or not. This includes the file path in the module tree under /lib/modules/$(uname -r), the license, the author, a short description, the list of dependencies (depends), and every parameter the module accepts when loaded. This parameter list matters because many drivers let you control their behaviour through module parameters, for example the debug level of a network driver or the maximum number of supported devices.
A common practical scenario: before loading an unfamiliar kernel module on a production system, you first check with modinfo which other modules must be loaded as a prerequisite, and whether the module is signed. Signed modules are mandatory when Secure Boot is active, and unsigned modules are otherwise rejected by the kernel with an error. The output of modinfo -F depends gives you exactly the dependency chain that modprobe will later resolve automatically.
# Show full metadata for a module, whether loaded or not
modinfo xfs
# Typical fields returned:
# filename: /lib/modules/6.8.0-generic/kernel/fs/xfs/xfs.ko
# license: GPL
# description: SGI XFS with ACLs, security attributes...
# depends: libcrc32c
# retpoline: Y
# intree: Y
# signature: (signed, appended)
# Query a single field, useful in scripts
modinfo -F depends xfs
modinfo -F version nf_tables
# List every parameter a module accepts
modinfo -p e1000e
# Check module signature status for Secure Boot compliance
modinfo -F signer nvidia 2>/dev/null || echo "module unsigned or not present"
4. modprobe: loading and unloading modules with dependency resolution
The central command for daily work is modprobe, because unlike insmod it automatically resolves every dependency of a kernel module and loads them in the correct order. Running modprobe nf_nat makes modprobe ensure nf_conntrack gets loaded first if missing, because nf_nat depends on it. This resolution is based on a database generated from the depends fields of every module under /lib/modules/$(uname -r), which has to be kept up to date with depmod, especially after manually copying new module files.
To unload, modprobe -r is used, which also works recursively: every module that came along automatically during loading and now has no other user gets removed as well. This differs clearly from rmmod, which only removes the exact kernel module specified and fails with an error when dependencies still exist. For testing purposes, modprobe --dry-run -v is useful because it shows the exact load order without changing anything.
# Load a module, resolving all dependencies automatically
modprobe nf_nat
# Dry run: show what WOULD be loaded, without changing anything
modprobe --dry-run -v nf_nat
# Load a module with custom parameters (not persisted across reboots here)
modprobe e1000e InterruptThrottleRate=3000
# Unload a module and every dependency no longer in use
modprobe -r nf_nat
# Rebuild the module dependency database after adding new module files
depmod -a
# Force a re-scan of module aliases (useful after driver package updates)
depmod -a "$(uname -r)"
5. insmod and rmmod: the direct, riskier path
insmod loads a kernel module directly from a given .ko file, without consulting the module database and without resolving dependencies itself. If a prerequisite is missing, the kernel reports an error such as Unknown symbol, and the administrator has to identify the missing modules manually and load them in the correct order. This path matters mostly when testing a self compiled driver, for example while developing a custom kernel module that is not yet installed under /lib/modules and not yet registered in the depmod database.
rmmod is the counterpart for unloading and also works without automatically resolving dependencies. Trying to remove a kernel module that is still referenced by another module fails with the error rmmod: ERROR: Module ... is in use. In production environments, modprobe -r is almost always preferred over rmmod, since automatic resolution avoids mistakes caused by forgotten dependencies. insmod and rmmod still matter as the precise, controlled tool for situations where you want to know exactly what is happening, for example while debugging a failing module load.
# Load a module directly from a .ko file (no dependency resolution)
sudo insmod /lib/modules/6.8.0-generic/kernel/drivers/net/dummy.ko
# If dependencies are missing, the kernel log shows something like:
# dummy: Unknown symbol register_netdevice (err -2)
# In that case, load the dependency first, then retry insmod
# Remove an exact module (fails if still referenced elsewhere)
sudo rmmod dummy
# Typical failure when dependencies still reference the module:
# rmmod: ERROR: Module nf_conntrack is in use by: nf_nat
# Force removal (dangerous, can destabilize the running kernel)
sudo rmmod -f some_module # avoid on production systems
6. Loading kernel modules automatically at boot
Systemd ships with /etc/modules-load.d/, a declarative mechanism for loading certain kernel modules automatically on every boot. Every file in this directory with a .conf extension holds a list of module names, one per line, and is processed by the systemd-modules-load.service at boot. This is the preferred path over the older /etc/modules, which is still used on systems without systemd but offers less structure for multiple configuration sources.
A typical example from the container world: for Docker or Podman to work reliably, the kernel modules overlay and br_netfilter must be loaded, the latter especially for correct bridge network filtering with iptables. If one of these modules is not loaded automatically at boot, container networking behaves inconsistently, often only fixed after a manual modprobe. Configuring this through modules-load.d makes the behaviour reproducible and documents at the same time which modules a system deliberately needs.
# /etc/modules-load.d/containers.conf
# Kernel modules loaded automatically at every boot via systemd-modules-load.service
overlay
br_netfilter
# /etc/modules-load.d/network.conf
# Bonding driver required for NIC teaming on this host
bonding
# Verify the service picked up the configuration after a reboot
# systemctl status systemd-modules-load.service
# journalctl -u systemd-modules-load.service --boot
7. Blacklisting modules and persisting parameters
Sometimes a kernel module should specifically not be loaded, even though the kernel would pick it automatically, for example because an alternative driver is preferred, or because a module has known stability issues with particular hardware. Blacklisting through files in /etc/modprobe.d/ with the directive blacklist modulename exists for exactly this. It is important to understand that blacklisting only prevents automatic loading via hardware detection (udev aliases), not an explicit modprobe modulename by an administrator or another module requesting it as a dependency.
For parameters meant to be permanent rather than valid for a single session only, the same /etc/modprobe.d/ files are used with the directive options modulename parameter=value. This is the correct place for production configuration, unlike parameters passed directly on a manual modprobe call, which are lost after a reboot. After changing files under /etc/modprobe.d/, the initramfs usually needs to be rebuilt (update-initramfs -u on Debian/Ubuntu, dracut -f on RHEL based systems) so that early boot stage modules also respect the new configuration.
# /etc/modprobe.d/blacklist-nouveau.conf
# Prevent the open-source nouveau driver from loading automatically,
# because the proprietary NVIDIA driver should take over instead.
blacklist nouveau
options nouveau modeset=0
# /etc/modprobe.d/network-tuning.conf
# Persist a module parameter across reboots for a specific NIC driver
options e1000e InterruptThrottleRate=3000
# After changing files in /etc/modprobe.d/, rebuild the initramfs so early
# boot stages also respect the new configuration:
# update-initramfs -u (Debian/Ubuntu)
# dracut -f (RHEL/CentOS/Fedora)
8. Troubleshooting: when a kernel module refuses to load
When an expected kernel module refuses to load, the first step is almost always dmesg, filtered by module name. The kernel writes every load failure with a concrete cause into the kernel ring buffer, such as missing symbols, a version mismatch between the compiled module and the running kernel, or a missing signature when Secure Boot is active. It is also worth checking journalctl -k, which stores the same kernel messages persistently across boots, while dmesg only shows the current boot unless configured for persistent storage.
A second common failure is a stale module database after a kernel update: if a new kernel was installed but depmod was not run for the new version, modprobe may not find the kernel module at all, even though the file physically exists. The command modprobe --show-depends modulename shows the resolved dependency chain and makes visible where the resolution breaks. For modules built through DKMS (Dynamic Kernel Module Support), it is also worth checking /var/lib/dkms/ to see whether the build for the currently running kernel version actually succeeded.
# First stop for module load failures: filter kernel ring buffer
dmesg | grep -i -A2 modulename
# Persistent kernel log across boots (systemd-journald with persistent storage)
journalctl -k --boot | grep -i modulename
# Show the resolved dependency chain modprobe would use
modprobe --show-depends modulename
# Confirm the module file actually exists for the running kernel
find /lib/modules/"$(uname -r)" -name "modulename.ko*"
# Rebuild module dependencies after a kernel update
sudo depmod -a "$(uname -r)"
# For DKMS-built modules: check build status for the current kernel
dkms status
9. Kernel module tools compared
Each of the tools described covers a different part of the kernel module lifecycle, and choosing the right one decides whether a change is reproducible and safe or only valid for the current session.
| Tool | Purpose | Resolves dependencies | Persists across reboot |
|---|---|---|---|
| lsmod | Show loaded modules | not applicable, display only | not applicable |
| modinfo | Check metadata | not applicable, display only | not applicable |
| modprobe | Load and unload | yes, automatically | no, only via modules-load.d |
| insmod / rmmod | Direct load/unload | no, manual | no |
| modules-load.d | Boot automation | uses modprobe internally | yes, permanent |
For daily operations this means: diagnose always with lsmod and modinfo, make active changes almost exclusively with modprobe, and configure permanent behaviour through /etc/modules-load.d/ and /etc/modprobe.d/. insmod and rmmod remain tools for targeted exceptions and kernel module development, not for standard management of production systems.
Mironsoft
Linux server administration and kernel level system diagnosis
Kernel issues nobody on the team can properly classify?
We analyze module load failures, driver problems and kernel log anomalies on your production systems, and bring them into a documented, reproducible state.
Module audit
Complete inventory of loaded kernel modules and their dependencies
Boot configuration
Setting up reproducible modules-load.d and modprobe.d configuration
Kernel diagnosis
Systematic troubleshooting for driver and loading problems
10. Summary
Working with kernel modules is one of the fundamental skills of Linux system administration, since almost every driver and many core subsystems are implemented as loadable modules. lsmod shows the current state, modinfo provides metadata and dependencies before loading, and modprobe is the central tool for safely loading and unloading with automatic dependency resolution. insmod and rmmod remain relevant for special cases where full control without automatic resolution is needed.
For production systems, permanent, documented configuration through /etc/modules-load.d/ and /etc/modprobe.d/ matters most, instead of loading modules manually without any traceability. Anyone diagnosing kernel module failures almost always starts with dmesg and journalctl -k, complemented by an up to date module database via depmod -a. This combination of display, loading and diagnostic tools covers the complete lifecycle of a kernel module.
Managing kernel modules — the key points at a glance
Checking status
lsmod shows loaded modules, modinfo shows metadata and dependencies even for unloaded modules.
Loading and unloading
modprobe resolves dependencies automatically, insmod/rmmod work directly on the file without resolution.
Boot configuration
/etc/modules-load.d/*.conf for automatic loading, /etc/modprobe.d/*.conf for blacklisting and parameters.
Troubleshooting
dmesg and journalctl -k show load failures, depmod -a fixes a stale module database.