Skip to main content

Building Your Own Linux Kernel Module: From Compilation to Troubleshooting

Published: April 24, 2026 Updated: May 25, 2026 Larry Qu 3 min read

Why Learn Kernel Modules

Kernel modules (.ko) allow us to extend kernel capabilities without recompiling the entire kernel. Common use cases:

  1. Device drivers.
  2. File system extensions.
  3. Network filtering and observability.
  4. Security auditing or low-level performance collection.

For operations and systems engineers, understanding the module compilation and loading process can significantly improve troubleshooting efficiency.

Minimal Runnable Example

Directory structure:

simplemodule/
 Makefile
 simplemodule.c

Makefile:

obj-m := simplemodule.o

all:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

simplemodule.c:

#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("CalmOps");
MODULE_DESCRIPTION("A minimal Linux kernel module");

static int __init simple_init(void)
{
  pr_info("simplemodule: loaded\n");
  return 0;
}

static void __exit simple_exit(void)
{
  pr_info("simplemodule: unloaded\n");
}

module_init(simple_init);
module_exit(simple_exit);

It is recommended to use pr_info/pr_err instead of bare printk for clearer semantics.

Compilation Steps

make

Common files after compilation:

  1. simplemodule.ko: the final module.
  2. Module.symvers: symbol version information.
  3. modules.order: module ordering.
  4. Various .cmd intermediate files.

Loading and Unloading

sudo insmod simplemodule.ko
lsmod | grep simplemodule

sudo rmmod simplemodule
lsmod | grep simplemodule

Check kernel logs:

dmesg | tail -n 30

In systemd environments, you can also use:

journalctl -k -n 50

insmod vs modprobe

  1. insmod only loads the specified .ko, without handling dependencies automatically.
  2. modprobe automatically resolves dependencies based on the module index, suitable for production.

If the module is installed in the standard path, it is recommended to use:

sudo modprobe simplemodule
sudo modprobe -r simplemodule

Common Errors and Troubleshooting

1) invalid module format

The cause is usually:

  1. The kernel version used during compilation does not match the currently running kernel.
  2. Architecture mismatch (x86_64/arm64).

Check:

uname -r
modinfo simplemodule.ko
file simplemodule.ko

2) unknown symbol

Indicates the module references a symbol not visible in the current kernel.

Resolution:

  1. Confirm whether the dependent module is loaded first.
  2. Check if the corresponding kernel feature is enabled in the kernel configuration.
  3. Check the exported symbol strategy (EXPORT_SYMBOL).

On systems with Secure Boot enabled, unsigned modules may fail to load.

Solutions:

  1. Use the distribution’s signing process.
  2. In enterprise environments, use unified signing and certificate distribution.
  3. Temporarily disable Secure Boot in experimental environments (with caution).

Development Environment Preparation

  1. Install the headers/build package matching the current kernel.
  2. Use a test machine or virtual machine; do not experiment on the production kernel directly.
  3. Keep serial port/console access available to avoid losing connectivity after a kernel crash.

Production Practice: Managing Modules with DKMS

For long-term third-party driver maintenance, DKMS is recommended:

  1. Automatically recompiles modules when the kernel is upgraded.
  2. Reduces manual maintenance costs caused by version drift.

Suitable use cases: network card, storage, virtualization drivers, etc.

Security and Stability Reminders

Kernel modules run in kernel space; any out-of-bounds access, null pointer, or concurrency bug can crash the system. Recommendations:

  1. Prioritize safe APIs provided by the kernel.
  2. Implement strict error handling and resource cleanup.
  3. Use static analysis and code review.
  4. Roll out gradually with small traffic before full deployment.

Summary

Compiling kernel modules is not complex; the difficulty lies in compatibility, troubleshooting, and long-term maintenance. Mastering make, insmod/modprobe, dmesg/journalctl, and version matching logic will solve most frontline issues.

For production environments, it is recommended to introduce automated builds, signing, and DKMS workflows early.

References

Comments

👍 Was this article helpful?