Loading learning content...
Kernel modules are not merely loaded and forgotten—they have a complete lifecycle that system administrators and developers must understand and manage. From initial loading with proper dependencies, through runtime configuration, to controlled unloading, each phase requires specific tools and techniques.
Effective module management goes beyond basic insmod and rmmod commands. It encompasses dependency resolution, automatic loading through udev, parameter configuration, blacklisting, debugging load failures, and maintaining modules across kernel updates. Mastery of these skills is essential for anyone working with Linux at a system level.
This page provides comprehensive coverage of the module management toolchain and the underlying kernel mechanisms that make it work.
By the end of this page, you will master the complete module management toolkit: insmod, rmmod, modprobe, lsmod, and modinfo. You'll understand dependency resolution, automatic module loading, configuration files, parameter handling, and techniques for debugging module loading failures.
Linux provides two primary commands for loading kernel modules: insmod and modprobe. Understanding their differences is crucial for effective module management.
insmod — Insert Module:
insmod is the low-level module loading tool. It takes an explicit path to a .ko file and attempts to load it directly:
$ sudo insmod /path/to/mymodule.ko
Characteristics of insmod:
.ko filemodprobe — Module Probe:
modprobe is the intelligent module loading tool. It uses module name (not path) and handles dependencies automatically:
$ sudo modprobe e1000e
| Feature | insmod | modprobe |
|---|---|---|
| Input | Full path to .ko file | Module name only |
| Dependencies | Manual (fails if missing) | Automatic resolution |
| Configuration | Parameters on command line only | Reads /etc/modprobe.d/ |
| Module path | Specified explicitly | Searches /lib/modules/$(uname -r)/ |
| Aliases | Not supported | Resolves device aliases |
| Blacklisting | Ignores blacklist | Honors blacklist |
| Use case | Development, single modules | Production, system administration |
123456789101112131415161718192021222324
# insmod examples$ sudo insmod ./mydriver.ko # Load from current directory$ sudo insmod /lib/modules/5.15.0/extra/mydriver.ko$ sudo insmod mydriver.ko debug=1 max_devices=4 # With parameters # Failure without dependencies:$ sudo insmod ./usb_storage.koinsmod: ERROR: could not insert module: Unknown symbol in module # modprobe examples$ sudo modprobe e1000e # Load by name, deps handled$ sudo modprobe -v e1000e # Verbose: show what's loadedinsmod /lib/modules/5.15.0/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko # modprobe with parameters$ sudo modprobe bonding mode=active-backup primary=eth0 # See what would be loaded without actually loading$ modprobe -n -v snd_hda_intelinsmod /lib/modules/5.15.0/kernel/sound/core/snd.koinsmod /lib/modules/5.15.0/kernel/sound/core/snd-timer.koinsmod /lib/modules/5.15.0/kernel/sound/core/snd-pcm.koinsmod /lib/modules/5.15.0/kernel/sound/pci/hda/snd-hda-core.koinsmod /lib/modules/5.15.0/kernel/sound/pci/hda/snd-hda-intel.koDuring development, use insmod with the explicit path to your compiled module. For production and installed modules, always use modprobe—it ensures dependencies are satisfied and configuration is applied correctly.
Modules often depend on symbols exported by other modules. The kernel cannot load a module with unresolved symbols, so dependencies must be loaded first. modprobe automates this through the modules.dep file.
modules.dep and depmod:
The depmod command scans all modules and generates dependency information:
$ sudo depmod -a # Regenerate for current kernel
$ sudo depmod -a 5.15.0 # Regenerate for specific kernel
depmod produces /lib/modules/$(uname -r)/modules.dep:
# Example modules.dep entries
kernel/drivers/usb/storage/usb-storage.ko: kernel/drivers/scsi/scsi_mod.ko
kernel/sound/pci/hda/snd-hda-intel.ko: kernel/sound/pci/hda/snd-hda-codec.ko kernel/sound/pci/hda/snd-hda-core.ko kernel/sound/core/snd-pcm.ko kernel/sound/core/snd.ko
Format: module.ko: dependency1.ko dependency2.ko ...
12345678910111213141516171819202122
# View dependencies for a specific module$ modinfo --field depends usb-storagescsi_mod,usb-common # Show full dependency tree$ modprobe --show-depends usb-storageinsmod /lib/modules/5.15.0/kernel/drivers/scsi/scsi_mod.koinsmod /lib/modules/5.15.0/kernel/drivers/usb/common/usb-common.koinsmod /lib/modules/5.15.0/kernel/drivers/usb/storage/usb-storage.ko # Reverse dependency: what uses this module?$ lsmod | grep scsi_modscsi_mod 253952 5 usb_storage,sd_mod,sr_mod,sg,libata # modules.dep.bin for fast binary lookup$ ls -la /lib/modules/$(uname -r)/modules.dep*-rw-r--r-- 1 root root 523264 Dec 15 10:00 modules.dep-rw-r--r-- 1 root root 365876 Dec 15 10:00 modules.dep.bin # Rebuild after installing new modules$ sudo depmod -a$ sudo depmod -A # Only check for changes (faster)Soft dependencies:
Some module relationships are optional—"nice to have" rather than required. These are soft dependencies declared in module metadata:
MODULE_SOFTDEP("pre: i2c_algo_bit");
MODULE_SOFTDEP("post: drm_kms_helper");
modprobe attempts to satisfy soft dependencies but doesn't fail if they're unavailable.
Circular dependencies (A requires B, B requires A) are forbidden and indicate a design flaw. The module system cannot resolve such cycles. If you encounter circular dependency errors, the module design needs refactoring or the dependency graph needs review.
Removing modules from the running kernel is handled by rmmod and modprobe -r. However, unloading is more complex than loading—the kernel must verify that removal is safe.
Basic unloading:
$ sudo rmmod mymodule # Low-level removal
$ sudo modprobe -r mymodule # With dependency handling
Reference counting:
Modules maintain a use count tracking how many kernel subsystems and other modules are using them. Unloading is only permitted when the count reaches zero:
12345678910111213141516171819202122232425262728293031
# View module reference counts$ lsmodModule Size Used bynvidia_drm 69632 3 # Used by 3 referencesnvidia_modeset 1236992 2 nvidia_drmnvidia 39313408 64 nvidia_modesetsnd_hda_intel 57344 0 # Not in use, can unload # Attempt to unload in-use module (fails)$ sudo rmmod nvidiarmmod: ERROR: Module nvidia is in use by: nvidia_modeset # Must unload dependents first$ sudo rmmod nvidia_drm$ sudo rmmod nvidia_modeset$ sudo rmmod nvidia # modprobe -r attempts to unload dependencies recursively$ sudo modprobe -r nvidia_drm# Attempts: nvidia_drm → nvidia_modeset → nvidia # Force removal (DANGEROUS - can crash system)$ sudo rmmod -f nvidia# Only works if kernel compiled with CONFIG_MODULE_FORCE_UNLOAD # Why a module might be "in use":# - Open file handles (/dev entries)# - Mounted filesystems (fs modules)# - Active network interfaces (net drivers)# - Referenced by other modules# - Kernel threads running module codeCommon unloading complications:
Well-designed modules clean up completely: free memory, unregister devices, stop threads, and release hardware. The module's exit() function handles this. Poorly designed modules may leak resources or refuse to unload gracefully.
Module behavior is configured through files in /etc/modprobe.d/. These configuration files affect how modprobe handles module loading, including parameters, aliases, and blacklisting.
Configuration file format:
Files in /etc/modprobe.d/ contain directives in a simple line-based format. Files must end in .conf to be processed.
$ ls /etc/modprobe.d/
alsa-base.conf
blacklist.conf
bonding.conf
intel-microcode.conf
iwlwifi.conf
nvidia.conf
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
# ======================================# Module Parameters (options directive)# ====================================== # Set default parameters for a moduleoptions bonding mode=1 miimon=100 max_bonds=2 # Intel WiFi power managementoptions iwlwifi power_save=0 11n_disable=1 # NVIDIA settingsoptions nvidia NVreg_PreserveVideoMemoryAllocations=1 # ======================================# Module Aliases (alias directive) # ====================================== # Create an alias for a modulealias eth0 e1000ealias wlan0 iwlwifi # Hardware aliases (auto-generated by modules.alias)alias pci:v00008086d00001539sv*sd*bc02sc00i* igb # ======================================# Blacklisting (blacklist directive)# ====================================== # Prevent module from loading automaticallyblacklist nouveaublacklist pcspkr # Note: blacklist doesn't prevent manual loading# Use 'install' directive for complete blocking # ======================================# Install/Remove Hooks (install/remove)# ====================================== # Run command instead of loading moduleinstall pcspkr /bin/false # Run custom script before loadinginstall mymodule /sbin/prepare-hardware && /sbin/modprobe --ignore-install mymodule # Run command before unloadingremove mymodule /sbin/cleanup-hardware; /sbin/modprobe -r --ignore-remove mymodule # ======================================# Soft Dependencies (softdep directive)# ====================================== # Specify soft dependency relationshipssoftdep iwlwifi pre: cfg80211softdep snd-hda-intel post: snd-hda-codec-realtek| Directive | Syntax | Purpose |
|---|---|---|
| options | options <module> <params> | Set default module parameters |
| alias | alias <name> <module> | Create alternative module names |
| blacklist | blacklist <module> | Prevent auto-loading by udev |
| install | install <module> <command> | Run command when loading module |
| remove | remove <module> <command> | Run command when removing module |
| softdep | softdep <module> pre: <deps> post: <deps> | Optional dependencies |
Use 'modprobe -c' to dump the effective configuration from all files. Use 'modprobe -c | grep <module>' to see settings for a specific module. This helps debug when configuration isn't working as expected.
Modern Linux systems load most modules automatically without administrator intervention. This plug-and-play functionality relies on cooperation between the kernel, udev, and the module alias system.
The device detection flow:
1. Hardware detected (boot, hotplug, scan)
↓
2. Kernel creates device in /sys
↓
3. Kernel sends uevent to userspace
↓
4. udev receives event
↓
5. udev reads device attributes (vendor, product, class)
↓
6. udev constructs modalias string
↓
7. udev calls modprobe with alias
↓
8. modprobe searches modules.alias for matching module
↓
9. Module loaded, driver binds to device
12345678910111213141516171819202122232425262728
# View aliases defined by a module$ modinfo e1000e | grep ^alias:alias: pci:v00008086d000015F3sv*sd*bc*sc*i*alias: pci:v00008086d000015F2sv*sd*bc*sc*i*alias: pci:v00008086d00001570sv*sd*bc*sc*i*... # View modalias for a device$ cat /sys/class/net/enp0s31f6/device/modaliaspci:v00008086d000015D6sv00001028sd000007A1bc02sc00i00 # Test which module would be loaded for an alias$ modprobe --resolve-alias 'pci:v00008086d000015D6sv*sd*bc02sc00i*'e1000e # View the modules.alias file$ grep -m 3 e1000e /lib/modules/$(uname -r)/modules.aliasalias pci:v00008086d000015F3sv*sd*bc*sc*i* e1000ealias pci:v00008086d000015F2sv*sd*bc*sc*i* e1000ealias pci:v00008086d00001570sv*sd*bc*sc*i* e1000e # Monitor module loading in real-time$ udevadm monitor --property &$ # (plug in USB device, watch output) # Manually trigger uevents (rescans devices)$ echo 1 > /sys/bus/pci/rescan$ udevadm triggerModule alias patterns:
Aliases use wildcard patterns to match device identifiers:
pci:vVVVVVVVVdDDDDDDDDsvSSSSSSSSsdssssssssbc**sc**i**
↓ ↓ ↓ ↓ ↓ ↓ ↓
vendor device subvendor subdevice class subclass interface
v prefix = vendor IDd prefix = device IDsv = subsystem vendorsd = subsystem devicebc = base classsc = subclass* = wildcardThis allows drivers to match broad categories (e.g., "all Intel network controllers") or specific devices.
Critical boot modules are loaded from initramfs before the root filesystem is available. The 'dracut' or 'mkinitrd' tools include necessary modules in initramfs based on detected hardware. After boot, udev triggers loading of remaining modules for hotplugged and secondary devices.
Several commands provide information about loaded modules and module files. These tools are essential for system administration and debugging.
lsmod — List Modules:
Displays currently loaded modules:
$ lsmod
Module Size Used by
e1000e 294912 0
nvidia_drm 69632 3
snd_hda_intel 57344 4
123456789101112131415161718192021222324252627282930313233343536373839404142
# lsmod - list loaded modules$ lsmod | head -5Module Size Used byrfkill 28672 2 bluetooth,cfg80211bluetooth 720896 5 btrtl,btintel,btbcm,bnep,btusbcfg80211 974848 3 iwlmvm,iwlwifi,mac80211 # modinfo - detailed module information$ modinfo e1000efilename: /lib/modules/5.15.0/kernel/drivers/net/ethernet/intel/e1000e/e1000e.kolicense: GPLdescription: Intel(R) PRO/1000 Network Driverauthor: Intel Corporation, <linux.nics@intel.com>srcversion: 1A2B3C4D5E6F7890alias: pci:v00008086d00001539sv*sd*bc*sc*i*depends: retpoline: Yintree: Yvermagic: 5.15.0-generic SMP mod_unloadparm: debug:Debug level (0=none,...,16=all)parm: copybreak:Copy breakpoint for copy-only-tiny-framesparm: TxIntDelay:Tx interrupt delay # Get specific field from modinfo$ modinfo -F vermagic e1000e5.15.0-generic SMP mod_unload $ modinfo -F parm e1000e | head -3debug:Debug level (0=none,...,16=all)copybreak:Copy breakpoint for copy-only-tiny-framesTxIntDelay:Tx interrupt delay # /proc/modules - raw kernel module info$ cat /proc/modules | grep e1000ee1000e 294912 0 - Live 0xffffffxxxxxxxxxx # /sys/module - per-module sysfs entries$ ls /sys/module/e1000e/coresize holders initsize initstate notes parameters refcnt srcversion taint uevent $ cat /sys/module/e1000e/parameters/debug0| Source | Type | Information Provided |
|---|---|---|
| lsmod | Command | Loaded modules, sizes, dependencies |
| modinfo | Command | Detailed metadata from .ko file |
| /proc/modules | Proc file | Raw module list with addresses |
| /sys/module/<name>/ | Sysfs dir | Per-module parameters and state |
| /sys/module/<name>/parameters/ | Sysfs dir | Current parameter values |
| /lib/modules/$(uname -r)/ | Directory | Available module files |
To see all parameters a module accepts with descriptions: 'modinfo -p <module>'. To see current values of parameters for a loaded module: 'cat /sys/module/<name>/parameters/*'. Some parameters can be changed at runtime by writing to these files.
Module loading can fail for various reasons. Systematic debugging helps identify and resolve the root cause.
Common error messages and causes:
| Error Message | Likely Cause | Resolution |
|---|---|---|
| Unknown symbol in module | Missing dependency or wrong kernel version | Check dependencies; rebuild for correct kernel |
| Invalid module format | Compiled for different kernel; corrupt file | Rebuild module for target kernel |
| Module version magic mismatch | Kernel/module version mismatch | Match kernel versions; use DKMS |
| Required key not available | Module signature invalid or missing | Sign module or disable signature enforcement |
| Operation not permitted | Secure Boot, blacklist, or SELinux/AppArmor | Check security policies and blacklists |
| Resource busy | Device/resource already claimed | Unload conflicting module first |
| No such file or directory | Module file not found | Run depmod; check module path |
123456789101112131415161718192021222324252627282930313233343536373839
# Step 1: Check kernel messages for detailed errors$ dmesg | tail -20[12345.678] mymodule: Unknown symbol kmalloc_caches (err 0)[12345.679] mymodule: Unknown symbol __kmalloc (err 0) # Step 2: Verify module is for correct kernel$ modinfo mymodule.ko | grep vermagicvermagic: 5.10.0-generic SMP mod_unload$ uname -r5.15.0-generic # Mismatch! # Step 3: Check symbol availability$ grep kmalloc /lib/modules/$(uname -r)/build/Module.symvers0x12345678 kmalloc vmlinux EXPORT_SYMBOL # Step 4: Verify dependencies exist$ modprobe --show-depends mymodulemodprobe: FATAL: Module mymodule not found.$ ls /lib/modules/$(uname -r)/extra/mymodule.kols: cannot access: No such file or directory # Step 5: Regenerate module database$ sudo depmod -a # Step 6: Check for blacklisting$ grep mymodule /etc/modprobe.d/*.conf/etc/modprobe.d/blacklist.conf:blacklist mymodule # Step 7: Check Secure Boot status$ mokutil --sb-stateSecureBoot enabled # Step 8: Debug with verbose modprobe$ sudo modprobe -v --first-time mymoduleinsmod /lib/modules/5.15.0/extra/mymodule.komodprobe: ERROR: could not insert 'mymodule': Invalid argument # Step 9: Try with strace for system call errors$ sudo strace modprobe mymodule 2>&1 | grep -E '(open|init_module)'Loading certain modules 'taints' the kernel, affecting support and bug reports. Check /proc/sys/kernel/tainted for taint status. Common taints: proprietary module (P), forced load (F), staging driver (C). Tainting doesn't prevent loading but may affect vendor support.
Effective module management is a cornerstone skill for Linux system administrators and kernel developers. We've covered the complete toolkit:
insmod for development (explicit path, no dependencies), modprobe for production (automatic dependencies, configuration).modules.dep, generated by depmod. Dependencies must be loaded in correct order; modprobe handles this automatically./etc/modprobe.d/ control parameters, aliases, blacklists, and install hooks. These apply to modprobe operations.What's next:
The power of kernel modules comes with significant security implications. The next page examines the security aspects of loadable modules—from malicious kernel code injection to module signing, mandatory access controls, and best practices for secure module management.
You now have comprehensive knowledge of module management—loading, unloading, configuration, automatic handling, and troubleshooting. These skills are essential for effective Linux system administration.