
Lsmod vs Modprobe: List Loaded Kernel Modules
There is no modprobe list modules command, and it trips up more people than it should. modprobe loads a module and everything it depends on, removes one with -r, and answers questions about configuration and dependencies. It does not list what is loaded. For that, run lsmod. To see what is available on disk, walk /lib/modules/$(uname -r). Use modprobe when you want dependencies resolved, not for a listing.
Last updated: 2026-07-21
Does modprobe have a list modules command?
No. Run modprobe --help and there is no list subcommand, because listing loaded state was never its job. modprobe inserts a module and its dependencies, removes one with -r, or prints configuration and dependencies with flags like -c and --show-depends. That is the whole scope.
The truth about what is loaded lives in the kernel, exposed through /proc/modules. modprobe reads its own config and the dependency map, not the live loaded set. So when a forum answer tells you to run modprobe list modules, two tools got welded together in someone's memory. Use lsmod for loaded, find or modprobe -c for available.
Both commands ship in the same package, Kmod. They are siblings, not the same command, and knowing that saves you the wrong syntax.
List loaded modules with lsmod

Run lsmod. It shows exactly what the kernel is using right now, in three columns: Module, Size, and Used by. Under the hood it reads /proc/modules and formats that raw file into rows you can actually scan.
Read the columns as a safety check. Module is the name you feed to other tools. Size is the memory footprint. Used by is a count plus the names of anything depending on it. A non-zero count means something leans on this module, so unloading it can cascade. Do not remove it blind.
For one entry, pipe to grep. For example, lsmod | grep kvm finds the line without scrolling. The same trick captures state around a change:
lsmod > before.txt
lsmod > after.txt
diff before.txt after.txt
When lsmod hides a field or its name-mangling confuses you, read the raw file: cat /proc/modules. Same data, no formatting, columns for load state and memory address. If you script against loaded state, parse /proc/modules, not lsmod output that a future release could reformat out from under you.
How does modprobe reflect what is already loaded?
Only indirectly, and that is worth knowing before you trust it. modprobe -r --dry-run module_name tells you whether a remove would even proceed, which reflects whether the module is loaded and in use. But that is a side effect, not a query.
To cross-reference honestly, pair the tools. modprobe -c dumps the full config and alias map; lsmod shows the live set. Compare them when an alias resolves to a module you did not expect. modprobe knows what could load and by what name. lsmod knows what did. Keep those two apart and half the confusion disappears.
Check whether one specific module is loaded
Three reliable checks, and one trap. Here is what I run first:
lsmod | grep -w nvme
cat /sys/module/nvme/initstate # "live" if loaded
grep -w nvme /proc/modules
/sys/module/<name> is the least ambiguous of the three. If the directory exists, the kernel knows that module, and initstate reads live when it is fully up. That beats grepping text every time.
The trap is grepping lsmod, getting nothing, and concluding the module is missing. A module can be built into the kernel instead of loadable, so it never shows in lsmod even though the feature is present and working. It can also load under a different name through an alias, so grepping the pretty name misses the real one. Check /sys/module/ first, and for built-ins, grep name /lib/modules/$(uname -r)/modules.builtin. A false negative from lsmod has sent plenty of people down the wrong hole.
List every module on disk, not just the loaded ones
Available modules sit under your kernel's tree. To list the files, walk it with find:
find /lib/modules/$(uname -r) -type f -name '*.ko*'
The *.ko* glob catches plain .ko files and compressed ones like .ko.xz or .ko.zst, which most distributions ship now. Pipe to | wc -l when you want a number for an audit.
The file list is not the authoritative loadable set, though. That comes from the dependency database. Run modprobe -c for the full resolved config, or read modules.dep, the file that records each module's dependencies and load order. depmod regenerates modules.dep after you add or remove a module. So if a freshly installed module will not load by name, run sudo depmod -a and try again. A stale dependency map is the classic reason for "the file is right there but modprobe cannot find it."
Where modules live and why uname -r decides which apply
Modules sit under /lib/modules/, one subtree per kernel version. The running kernel picks its own tree by version string, which is why nearly every command wraps $(uname -r). Want the build date and architecture too? Run uname -a.
The tree groups modules by what they do:
| Purpose | On-disk path | When it loads |
|---|---|---|
| Network driver | /lib/modules/VERSION/kernel/net/ | Device appears or udev event |
| Filesystem support | /lib/modules/VERSION/kernel/fs/ | Mount attempt or manual load |
| Storage adapter | /lib/modules/VERSION/kernel/drivers/scsi/ | Boot or device detection |
Here is the gotcha nobody warns you about. Upgrade your kernel, skip the reboot, and uname -r still reports the old version. Now find /lib/modules/$(uname -r) points at the old tree while the new modules sit in a directory the running kernel ignores. modprobe fails with a module that "does not exist," and you burn twenty minutes chasing a ghost before you notice the version string. Reboot into the new kernel, or point at the exact version directory by hand. For the full mechanism, see this guide to dynamic module loading on Linux.
Available versus loaded, and why the difference bites
A module on disk is a file. A module in the kernel is running code. Confuse the two and you write bad troubleshooting steps.
Here is what happens. You find the .ko file, confirm it exists, and decide the driver is active. It is not. It is present but never loaded, because no device triggered it and nothing called modprobe. The feature stays dead until something loads it. A built-in module is the reverse: active, doing its job, and invisible to find because it was compiled straight into vmlinuz.
So check the state you actually care about. Debugging a missing feature? Read loaded state with /sys/module/ or lsmod. Planning a change or packaging one up? Read the disk file with modinfo. Ask the question that matches the tool.
How do you list device drivers, not just modules?
Not every driver is a loadable module, so lsmod alone gives you half the picture. Bind the hardware to its driver instead:
lspci -k # PCI devices with "Kernel driver in use"
lsusb -v # verbose USB, including bound drivers
ls /sys/bus/pci/drivers/ # every registered PCI driver
lspci -k is the one I reach for most. It prints each device with the exact kernel driver bound to it, which answers "what is actually running this card" far better than staring at a module list. A device with no "Kernel driver in use" line is your unsupported hardware, and it is telling you so plainly.
The /sys/bus/*/drivers/ directories list every driver the kernel registered, module or not. It is the closest thing Linux has to a single driver registry. Built-in drivers show up here even though they never touch lsmod, which is exactly why this beats a module dump when you are chasing missing hardware support.
Inspect a module with modinfo
Use modinfo module_name when you need trustworthy detail. It prints the fields that tie the running artifact to the file on disk: filename (the absolute .ko path), description, alias, depends (comma-separated), parm (each parameter with its type), and license.
Read filename to confirm the exact path before you package or replace a file. Read depends before you unload anything, so you know what has to come out first. Do not append .ko to the name. The file ends in .ko; the name does not.
A few flags earn their keep:
modinfo -n e1000eprints only the filename, handy in scripts.modinfo -p e1000elists parameters.modinfo -F depends e1000eprints one field.
For dependencies the way modprobe will actually resolve them, run modprobe --show-depends module_name. It prints the full insmod chain in load order, which modinfo depends does not. Treat that output as authoritative for the running build before you touch anything.
How do you diagnose a module that will not load?
Stop scrolling lsmod and read why it failed. Load it with verbose output first:
sudo modprobe -v module_name
-v prints each insmod line as it inserts dependencies, so you see exactly which link in the chain broke. If it still fails without a word, read the kernel ring buffer:
sudo dmesg | tail -20
journalctl -k -b | tail -20
That tells you the real reason instead of a generic error. The usual suspects: a missing dependency (fix with depmod -a), a version mismatch because you are on the wrong kernel tree, or a rejected signature. With UEFI Secure Boot on and module.sig_enforce active, an unsigned or wrongly signed module refuses to load and dmesg says so, usually with a line about a bad or missing key. Sign the module against an enrolled key or the load keeps failing no matter how many times you retry.
If the module loads but misbehaves, its live settings sit under /sys/module/<name>/parameters/. Read those to see what the module actually thinks its parameters are, not what you meant to pass. When the message still makes no sense, the module source and its MODULE_PARM_DESC strings are the last word. Reading the source beats guessing from a forum answer that pattern-matched a different failure.
To stop a driver that is wrecking a boot, edit the boot loader entry. At the menu, find the line starting with linux and append modprobe.blacklist=module_name, then boot once. That is temporary and dies at the next reboot. For a fix that sticks and avoids the sharp edges, follow a proper method for safely blacklisting kernel modules.
Operational habits that save you a rollback
A few rules I do not skip:
- Prefer
modprobeoverinsmodandrmmod. It handles dependencies and load order, which is what keeps a production box standing. - Snapshot state before and after a change.
lsmod > /tmp/state.txtcosts nothing and proves what was there when someone asks. - Schedule unloads for a maintenance window. An unplanned
modprobe -rcan pull the rug from a running service and force a reboot. - Make persistent loads explicit: drop a file under
/etc/modules-load.d/with one module name per line, no.ko. See the walkthrough on making a module load at boot if it does not take.
FAQ
Why does lsmod show nothing for a driver that is clearly working?
The driver is compiled into the kernel, not loaded as a separate module. Built-in code never appears in lsmod or /proc/modules. Confirm it with grep name /lib/modules/$(uname -r)/modules.builtin, or run lspci -k to see the driver bound to the device.
Do I include the .ko extension when I name a module?
Never with modprobe, modinfo, or config files. Those tools want the bare module name, and the on-disk file just happens to end in .ko or .ko.xz. Pass the extension and the command fails to resolve the name. The only place the full filename shows up is modinfo output.
How do I list modules for a kernel I am not currently running?
Point the path straight at that version: find /lib/modules/5.15.0-generic -type f -name '*.ko*'. This matters right after a kernel upgrade, when uname -r still reports the old version until you reboot. Do not lean on $(uname -r) in that window.
Is there a single command that lists both loaded and available modules?
No, and doing it honestly takes two steps. Pull loaded state from lsmod or /proc/modules, and available state from find over the modules tree or modprobe -c. Any one-liner claiming to do both is quietly reading one source and ignoring the other.
What rebuilds the dependency list after I add a module?
sudo depmod -a. It scans the modules tree and regenerates modules.dep, the file modprobe reads to work out load order. If a freshly copied module loads with insmod but not modprobe, a stale dependency map is almost always the reason.
Related: Linux Kernel Modules: Load, Unload, and Troubleshoot
