How to Use modprobe for Kernel Modules with Softlinks and depmod
Stop manually tracking load order. Let modprobe read the dependency file and handle everything — softlinks, depmod, and automatic cleanup included. so let us discuss more about modprobe for Kernel Modules
- The Problem with insmod
- What is modprobe?
- How modprobe Knows Dependencies — modules.dep
- Creating Softlinks — Registering Your Module
- Running depmod -a — Rebuilding the Dependency Map
- Loading with modprobe — Full Walkthrough
- Removing Modules with modprobe -r
- insmod vs modprobe — When to Use Which
- Common Mistakes and Fixes
- Summary
01 The Problem with insmod
In the previous article we loaded our stacked modules using insmod. It worked, but we had to do everything manually — load mod1 first, verify the symbol in /proc/kallsyms, then load mod2. If we forgot the order, the kernel threw an Unknown symbol error.
Now imagine you are working on a production driver with five or six stacked layers. Remembering the exact load sequence every time you reboot — or asking a tester to do it — is a recipe for mistakes. There has to be a better way, and there is: modprobe. modprobe for Kernel Modules
❌ With insmod (Manual)
- You must know and remember the load order
- You must load each dependency separately
- Easy to get wrong, especially after a reboot
- Unloading is also manual and reversed
✅ With modprobe (Automatic)
- Just say:
modprobe mod2 - modprobe reads the dependency map and loads mod1 automatically
- No need to track order yourself
modprobe -r mod2removes everything cleanly
02 What is modprobe?
modprobe is the smart module loader. Unlike insmod which blindly tries to load a single .ko file, modprobe first consults a pre-built dependency map called modules.dep. It reads which other modules your target module depends on, loads those first in the correct order, and only then loads the module you actually asked for.
Think of it like a package manager — when you install a package, it automatically pulls in all required dependencies. modprobe does the same for kernel modules.
User types: sudo modprobe mod2
┌────────────────────────────────────────┐
│ modprobe │
│ 1. Open /lib/modules/$(uname -r)/ │
│ modules.dep │
│ 2. Find entry for mod2.ko │
│ 3. See: mod2.ko depends on mod1.ko │
│ 4. Load mod1.ko first (insmod) │
│ 5. Load mod2.ko second (insmod) │
└────────────────────────────────────────┘
Result: both modules loaded, correct order, zero manual effort
💡
modprobe is actually a userspace tool, part of the kmod package. When you run it, it reads modules.dep, figures out the dependency chain, and internally calls insmod for each module in the right order. The kernel itself never sees modprobe — it only sees the individual insmod calls.03 How modprobe Knows Dependencies — modules.dep
The brain of modprobe is a file called modules.dep. It lives here on your system: so let us study how modprobe for Kernel Modules works
/lib/modules/$(uname -r)/modules.dep # For example on kernel 6.8.0-90-generic: /lib/modules/6.8.0-90-generic/modules.dep
The format of this file is straightforward. Each line looks like this:
# target_module: dependency1 dependency2 ...
kernel/drivers/misc/mod2.ko: kernel/drivers/misc/mod1.ko
kernel/drivers/misc/mod1.ko:
Read it like this: “To load mod2.ko, you must first load mod1.ko.” mod1.ko has no dependencies, so its line has nothing after the colon.
This file is not something you edit by hand. It is automatically generated by a tool called depmod, which we will look at in a moment. But first, we need to tell the kernel where our custom modules live — and that is where softlinks come in.
04 Creating Softlinks — Registering Your Module
Here is something important to understand: modprobe only looks for modules inside /lib/modules/$(uname -r)/. Your compiled .ko files are sitting in your home directory — modprobe has no idea they exist.
We have two options: copy the .ko files into the kernel module tree, or create a symbolic link (softlink) pointing from the module tree to our actual files. The softlink approach is much better during development because if you recompile the module, the link automatically points to the updated file — no copying needed.
What is a Softlink?
A softlink is like a shortcut. It is a special file that just points to another file located elsewhere. When the kernel reads the softlink, it transparently accesses the actual file at the target path.
/lib/modules/6.8.0-90-generic/kernel/drivers/misc/
mod1.ko ──────────────────────────────────────────► /home/raviteja/.../mod1.ko
mod2.ko ──────────────────────────────────────────► /home/raviteja/.../mod2.ko
The .ko files stay in your project folder.
modprobe reads through the link transparently.
Creating the Softlinks
The command to create a softlink is ln -s <source> <destination>. We place the link inside the misc driver directory of the running kernel’s module tree:
Terminal — Create softlinks for mod1 and mod2
⚠️
ln -s. If you use a relative path, the link breaks the moment you run the command from a different directory. Always start with /home/... not ./.05 Running depmod -a — Rebuilding the Dependency Map
Now that the softlinks are in place, modprobe still does not know about our modules. Remember — modprobe reads from modules.dep, and that file has not been updated yet. We need to run depmod -a to regenerate it.
Terminal — Run depmod
What does depmod -a actually do? It walks the entire /lib/modules/$(uname -r)/ directory, reads every .ko file, looks at their unresolved symbols and exported symbols, and figures out who depends on whom. The result is written back into modules.dep.
Let us verify that our modules appeared in the file:
Terminal — Inspect modules.dep
viteja@raviteja-Inspiron-15-3511:/lib/modules/6.8.0-90-generic/kernel/drivers/misc$ grep mod /lib/modules/6.8.0-90-generic/modules.dep
kernel/drivers/misc/mod1.ko:
kernel/drivers/misc/mod2.ko: kernel/drivers/misc/mod1.ko
There it is. modules.dep now knows that mod2 depends on mod1. modprobe will use this information every time someone asks it to load mod2.
✅
sudo depmod -a again. If you skip this step, modprobe works with stale dependency information and may fail or load the wrong version.What is modules.dep.bin?
You might notice a modules.dep.bin file alongside modules.dep. This is just a binary-encoded version of the same information — modprobe reads the .bin version at runtime because it loads faster than parsing text. depmod -a generates both files automatically, so you never need to worry about .bin directly.
06 Loading with modprobe — Full Walkthrough
Everything is set up. Softlinks are created, depmod -a has run, and modules.dep has the dependency entry. Now watch how simple the load becomes:
1 Just load mod2 — do not load mod1 manually. Let modprobe figure it out.
2 Check lsmod — you will see both mod1 and mod2 are loaded, even though you only asked for mod2.
3 Check dmesg — both init functions ran, in the correct order: mod1 first, mod2 second.
Terminal — Full modprobe walkthrough
✅
lsmod output carefully. The 1 in mod1’s row (third column) means it has one user — mod2. And the word mod2 at the end confirms which module is using it. This is the kernel’s built-in dependency tracking in action.What Just Happened Under the Hood?
When you ran sudo modprobe mod2, here is the exact sequence of events:
sudo modprobe mod2
│
▼
┌─ modprobe reads modules.dep ──────────────────────┐
│ Found: mod2.ko depends on mod1.ko │
└───────────────────────┬───────────────────────────┘
│
┌────────────────┴─────────────────┐
▼ ▼
┌── Step 1 ──────────┐ ┌── Step 2 ──────────┐
│ insmod mod1.ko │ then │ insmod mod2.ko │
│ (dependency) │ ──────►│ (requested) │
└────────────────────┘ └────────────────────┘
Both modules loaded. Correct order. Zero effort from you.
07 Removing Modules with modprobe -r
Just like loading, unloading with modprobe is also automatic. You only need to ask it to remove mod2, and it will unload both modules in the correct reverse order — mod2 first, then mod1.
Terminal — Remove modules with modprobe -r
💡
modprobe -r only removes a dependency module (mod1 in this case) if no other loaded module still needs it. If some other third module was also using mod1, modprobe would remove mod2 but leave mod1 in place. The reference count protects against accidental removal of shared modules.08 insmod vs modprobe — When to Use Which
Both tools load kernel modules. Understanding when to reach for each one saves a lot of debugging time.
| Feature | insmod | modprobe |
|---|---|---|
| Resolves dependencies | ❌ No — you do it manually | ✅ Yes — automatically |
| Needs module in /lib/modules | ❌ No — works from any path | ✅ Yes — or a softlink to it |
| Reads modules.dep | ❌ No | ✅ Yes |
| Needs full path to .ko | ✅ Yes | ❌ No — just use module name |
| Best for | Quick single-module testing | Multi-module drivers, production use |
| Unload command | rmmod <module> |
modprobe -r <module> |
During your early development sessions — editing code, recompiling, testing a single module — insmod is perfectly fine and faster. Once your driver has dependencies and you want to test it more realistically or share it with someone else, switch to modprobe.
09 Common Mistakes and Fixes
| Problem | Why it happens | How to fix it |
|---|---|---|
modprobe: FATAL: Module mod2 not found |
Softlink not created or depmod not run | Create softlinks then run sudo depmod -a |
| modprobe loads old version of module | Recompiled module but forgot to rerun depmod | Always run sudo depmod -a after recompiling |
| Softlink created but modprobe still fails | Relative path used in ln -s — link is broken |
Delete and recreate link with full absolute path |
modprobe -r only removes mod2, not mod1 |
Another module is also using mod1 (use count > 0) | Normal behaviour — remove all users of mod1 first |
| Softlink destination already exists error | Softlink from a previous session still exists | Remove old link: sudo rm /lib/modules/.../mod1.ko |
🚫
/lib/modules/. Only create softlinks to your custom modules in the misc or a dedicated subdirectory. Accidentally removing a system module can make your kernel unbootable. so now you know how modprobe for Kernel Modules works.10 Summary
What We Covered in This Article
- insmod is manual — you track load order yourself. modprobe is smart — it reads a dependency map and handles everything.
modules.depis the dependency map file. It lives in/lib/modules/$(uname -r)/and maps each module to its required dependencies.- Softlinks let you register your out-of-tree module with the kernel module tree without copying the file. Use
ln -s <full_src_path> <dest_in_module_tree>. depmod -awalks the module tree, figures out dependencies from exported and undefined symbols, and rebuildsmodules.dep. Always run it after creating or updating links.modprobe mod2automatically loads mod1 first (because modules.dep says so), then mod2. No manual ordering needed.modprobe -r mod2removes both modules cleanly in reverse order — mod2 first, then mod1 — as long as mod1 has no other users.- Use
lsmodto verify loaded modules and their use counts. Usedmesgto see init/exit log messages and confirm everything ran in the right order.
Final summary:
raviteja@raviteja-Inspiron-15-3511:~/lsyspg/kernel_programming/Day7/export_module$ ls
Makefile mod1.c mod1.ko mod1.mod mod1.mod.c mod1.mod.o mod1.o mod2.c mod2.ko mod2.mod mod2.mod.c mod2.mod.o mod2.o module.c modules.order Module.symvers
raviteja@raviteja-Inspiron-15-3511:~/lsyspg/kernel_programming/Day7/export_module$ uname -r
6.8.0-106-generic
raviteja@raviteja-Inspiron-15-3511:~/lsyspg/kernel_programming/Day7/export_module$ sudo ln -s /home/raviteja/lsyspg/kernel_programming/Day7/export_module/mod1.ko \
/lib/modules/6.8.0-106-generic/kernel/drivers/misc/mod1.ko
raviteja@raviteja-Inspiron-15-3511:~/lsyspg/kernel_programming/Day7/export_module$ sudo ln -s /home/raviteja/lsyspg/kernel_programming/Day7/export_module/mod2.ko \
/lib/modules/6.8.0-106-generic/kernel/drivers/misc/mod2.ko
raviteja@raviteja-Inspiron-15-3511:~/lsyspg/kernel_programming/Day7/export_module$ sudo depmod -a
raviteja@raviteja-Inspiron-15-3511:~/lsyspg/kernel_programming/Day7/export_module$ sudo modprobe mod2
raviteja@raviteja-Inspiron-15-3511:~/lsyspg/kernel_programming/Day7/export_module$
output in dmesg
[ 5583.250528] module1_init:module 1 init
[ 5583.251779] mod2_init: in mod2 init
[ 5583.251790] myadd sum of 3+5=8
[ 5583.251794] mod2_init: add=8
hope you understood how simple the modprobe for Kernel Modules is
Free learning to all!!
EmbeddedPathashala.
