Modules Programming Basics: Master Ultimate Guide to Linux Kernel Modules (2026)

On: January 3, 2026
Modules Programming Basics

Learn Modules Programming Basics in Linux with clear examples, step-by-step guidance, and beginner-friendly explanations for efficient kernel module development.

If you are starting your journey into Linux kernel development, modules programming basics is one topic you simply cannot skip. Kernel modules are the safest, cleanest, and most practical way to learn how the Linux kernel really works without constantly rebuilding the entire kernel.

Think of kernel modules like plugins for the Linux kernel. You load them when needed, unload them when you are done, and keep your system flexible and clean. Whether you want to write a device driver, add debugging support, or experiment with kernel internals, understanding module programming basics is step one.

What Are Kernel Modules and Why Do They Matter?

A kernel module is a piece of code that runs inside the Linux kernel space and can be inserted or removed at runtime. Unlike user-space programs, kernel modules have direct access to hardware and core kernel services.

Why does this matter?

Because without kernel modules:

  • Every driver change would require a full kernel rebuild
  • Development would be slow and risky
  • Debugging would be painful

With kernel modules:

  • You can load features dynamically
  • You can test drivers safely
  • You can keep the kernel small and modular

This is why modules programming basics is considered the foundation of Linux kernel programming.

Kernel Module vs Monolithic Kernel Code

Let’s clear one common confusion early.

  • Monolithic kernel code is compiled directly into the kernel image
  • Kernel modules are compiled separately and loaded at runtime

Most modern Linux drivers are built as modules because:

  • They reduce boot time
  • They save memory
  • They are easier to maintain

As a beginner, modules give you fast feedback. You write code, build it, load it, test it, unload it, repeat. No reboot needed.

Your First Look at a Kernel Module

At its core, a kernel module is just a C file with two special functions:

  • An initialization function
  • A cleanup function

These tell the kernel:

  • What to do when the module is loaded
  • What to do when the module is removed

This simple structure is what makes modules programming basics approachable, even for newcomers.

Building Kernel Module Binary

One of the most searched topics in modules programming basics is how to actually build a kernel module binary.

Unlike normal C programs, kernel modules:

  • Do not use libc
  • Are compiled against kernel headers
  • Produce a .ko file instead of an executable

Basic Requirements

To build a kernel module, you need:

  • Linux kernel headers
  • GCC
  • Make

Simple Kernel Module Makefile

Here is a minimal Makefile used for building kernel module binaries:

obj-m += hello_module.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

What is happening here?

  • obj-m tells the kernel build system this is a module
  • The kernel build directory provides the correct compiler flags
  • The output is a .ko file

This build process is a core part of modules programming basics and something you will use daily as a kernel developer.

Loading and Unloading Kernel Modules

Once the kernel module binary is built, you interact with it using standard tools.

Loading a Module

sudo insmod hello_module.ko

Unloading a Module

sudo rmmod hello_module

Checking Loaded Modules

lsmod

These tools let you work with modules without rebooting, which is one of the biggest advantages of module-based development.

Tools for Module Management

Linux provides powerful tools for managing kernel modules. Understanding these tools is a must when learning modules programming basics.

insmod

  • Loads a module by file path
  • Does not resolve dependencies

rmmod

  • Removes a module from the kernel

modprobe

  • Loads modules with dependency handling
  • Preferred tool in real systems

lsmod

  • Shows all loaded modules
  • Displays dependency relationships

modinfo

  • Shows module metadata
  • Useful for debugging and verification

These tools work together to give you full control over module lifecycle management.

Tracking Module Dependency

Kernel modules often depend on other modules. For example, a filesystem driver may rely on core block device modules.

This is where tracking module dependency becomes important.

How Dependencies Are Managed

  • The kernel tracks symbol usage
  • Dependencies are recorded during module build
  • depmod generates dependency maps

Viewing Dependencies

lsmod

The output shows:

  • Module name
  • Size
  • Which modules depend on it

Why modprobe Matters

Unlike insmod, modprobe:

  • Automatically loads dependent modules
  • Prevents missing symbol errors

Understanding dependency tracking is essential in real driver development and a key part of modules programming basics.

Module Parameters Explained Simply

Module parameters allow you to pass values to a kernel module at load time. Think of them as command-line arguments for kernel code.

This feature alone makes modules extremely flexible.

Defining Module Parameters

static int debug = 0;
module_param(debug, int, 0644);

Passing Parameters

sudo insmod mymodule.ko debug=1

Why Module Parameters Matter

  • Enable debugging without recompiling
  • Configure behavior dynamically
  • Used heavily in production drivers

Module parameters are widely used in real systems and understanding them is a core part of modules programming basics.

Understanding the Kernel Symbol Table

The kernel symbol table is one of those topics that sounds scary but is actually very logical.

The kernel symbol table:

  • Contains exported symbols
  • Allows modules to access kernel functions
  • Enables communication between modules

Viewing Kernel Symbols

cat /proc/kallsyms

This file lists:

  • Function names
  • Variable names
  • Memory addresses

When a module is loaded, the kernel checks this table to resolve symbols used by the module.

If a symbol is not found, the module fails to load.

Exporting Module Symbols

Sometimes, you want one module to use functions from another module. This is where exporting module symbols comes in.

Exporting a Symbol

void my_helper_function(void)
{
    printk(KERN_INFO "Helper function called\n");
}

EXPORT_SYMBOL(my_helper_function);

Now other modules can use my_helper_function.

Why Export Symbols?

  • Share common logic
  • Split large drivers into smaller modules
  • Build layered kernel designs

This concept is critical in real-world kernel development and often appears in interviews related to modules programming basics.

Kernel Module Licensing and Why It Matters

Every kernel module must declare its license.

MODULE_LICENSE("GPL");

Why is this important?

  • Some kernel symbols are GPL-only
  • Non-GPL modules cannot access them
  • The kernel enforces this at load time

If you forget this, you may see warnings or missing symbol errors.

Debugging Kernel Modules Like a Pro

Debugging kernel code is different from user-space debugging.

Common Debugging Techniques

  • printk for logging
  • dmesg for viewing kernel logs
  • Dynamic debug
  • Kernel crash dumps

Example:

printk(KERN_INFO "Module loaded successfully\n");

Kernel debugging is an art, and mastering it starts with solid module programming basics.

Common Mistakes Beginners Make

Let’s save you some pain.

Frequent Errors

  • Forgetting to clean up resources
  • Incorrect module parameters
  • Missing symbol exports
  • Using blocking calls in wrong context

Every kernel developer makes these mistakes. The key is understanding why they happen.

How Modules Programming Basics Helps Your Career

If you are targeting:

  • Embedded Linux roles
  • Kernel driver positions
  • BSP development
  • Automotive Linux jobs

Then mastering modules programming basics is not optional. Interviewers expect you to understand:

  • Module lifecycle
  • Dependency handling
  • Symbol exporting
  • Build systems

This knowledge separates real kernel developers from tutorial followers.

Practical Learning Path

Here is a simple roadmap:

  1. Write a hello world module
  2. Add module parameters
  3. Export symbols
  4. Create two dependent modules
  5. Debug load failures
  6. Explore real drivers in /drivers

This hands-on path builds confidence fast.

If kernel modules are the entry gate to kernel development, then character device drivers are where theory finally meets reality.

Most beginners understand what a kernel module is, but they get stuck when asked a simple question in interviews:

“How does a character driver actually work end to end?”

In this guide, we will do two important things:

  1. Walk through a real character driver module, step by step
  2. Break down lsmod and /proc internals so you understand what the kernel is really tracking behind the scenes

This is a natural continuation of modules programming basics, and once this clicks, Linux kernel development stops feeling mysterious.

What Is a Character Driver in Simple Words?

A character driver is a kernel module that allows user-space programs to talk to hardware or kernel services using a stream of bytes.

Key traits of character drivers:

  • Data is transferred byte by byte
  • Accessed using file operations like open, read, write, close
  • Appears as a device file in /dev

Examples you already use:

  • /dev/tty
  • /dev/console
  • /dev/null

Character drivers are the best starting point because they teach:

  • Kernel to user communication
  • File operations inside the kernel
  • Device registration and cleanup

High-Level Flow of a Character Driver

Before touching code, let’s understand the flow.

  1. Module loads into the kernel
  2. Driver registers a character device number
  3. Kernel creates a device entry
  4. User program opens /dev/mydevice
  5. Kernel routes calls to driver functions
  6. Module unloads and cleans everything

This flow is the backbone of character driver development.

Real Character Driver Module: Step-by-Step Walkthrough

Now let’s walk through a minimal but real character driver.

Step 1: Include Required Kernel Headers

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

These headers provide:

  • Module macros
  • Kernel logging
  • File operation structures
  • User-kernel memory copy helpers

Step 2: Define Device Information

#define DEVICE_NAME "mychardev"
static int major_number;

The major number is how the kernel knows which driver handles which device.

Step 3: Implement File Operations

These are the heart of a character driver.

static int my_open(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "Device opened\n");
    return 0;
}

static int my_release(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "Device closed\n");
    return 0;
}

static ssize_t my_read(struct file *file, char __user *buffer,
                       size_t len, loff_t *offset)
{
    printk(KERN_INFO "Read requested\n");
    return 0;
}

What is happening here?

  • open runs when user opens /dev/mychardev
  • read runs when user reads from it
  • release runs when file is closed

This mirrors user-space file behavior, which is why character drivers feel familiar.

Step 4: Map File Operations to the Driver

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = my_open,
    .read = my_read,
    .release = my_release,
};

This structure tells the kernel:
“When someone accesses this device, call these functions.”

Step 5: Register the Character Device

static int __init my_init(void)
{
    major_number = register_chrdev(0, DEVICE_NAME, &fops);
    if (major_number < 0) {
        printk(KERN_ALERT "Failed to register device\n");
        return major_number;
    }

    printk(KERN_INFO "Registered with major number %d\n", major_number);
    return 0;
}

Key points:

  • 0 means kernel assigns a major number dynamically
  • Registration connects your driver to the kernel VFS
  • This is a core concept in modules programming basics

Step 6: Cleanup on Module Removal

static void __exit my_exit(void)
{
    unregister_chrdev(major_number, DEVICE_NAME);
    printk(KERN_INFO "Device unregistered\n");
}

Kernel code must always clean up.
If you forget this, you crash systems in real products.

Step 7: Module Metadata

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kernel Developer");
MODULE_DESCRIPTION("Simple Character Driver");

Without this, your module is incomplete.

Building and Testing the Character Driver

Build the Module

Use the same kernel module Makefile you already learned.

Load the Module

sudo insmod mychardev.ko

Check Kernel Log

dmesg

You will see the assigned major number.

Create Device Node

sudo mknod /dev/mychardev c <major> 0

Now your driver is accessible from user space.

Test from User Space

cat /dev/mychardev

You should see kernel logs confirming read access.

Congratulations.
You just walked through a real character driver module.

How lsmod Really Works Internally

Most people use lsmod without knowing what it does.

Let’s fix that.

What lsmod Shows

lsmod

Output columns:

  • Module name
  • Size
  • Used by (dependency count)

This data does not come from nowhere.

lsmod Reads From /proc/modules

Internally, lsmod reads:

/proc/modules

This file is generated by the kernel dynamically.

It contains:

  • Loaded module list
  • Memory usage
  • Reference counts
  • Dependency information

So when you load your character driver, it instantly appears here.

Understanding /proc Internals Like a Kernel Developer

The /proc filesystem is a virtual filesystem.
Files here do not exist on disk.

They are views into kernel data structures.

Important /proc Files for Module Developers

/proc/modules

  • Tracks loaded kernel modules
  • Used by lsmod

/proc/kallsyms

  • Kernel symbol table
  • Lists exported functions and variables

/proc/devices

  • Lists registered character and block devices
  • Shows major numbers

Example:

cat /proc/devices

You will see your character driver listed under character devices.

How /proc Connects to Modules Programming Basics

When you:

  • Register a device
  • Export a symbol
  • Load a module

The kernel updates internal structures that /proc exposes.

That means:

  • /proc is not magic
  • It is a debug window into kernel state

Understanding this gives you confidence during debugging.

How Module Dependencies Appear in /proc

When a module depends on another:

  • Kernel tracks symbol usage
  • Reference counts increase
  • /proc/modules reflects this relationship

This is how modprobe safely loads and unloads modules.

Why Interviewers Love These Topics

Interviewers ask about:

  • Character driver flow
  • lsmod output
  • /proc internals

Not because they want commands, but because these topics prove:

  • You understand kernel architecture
  • You can debug real systems
  • You know how kernel modules live and die

Mastering this puts you ahead of most candidates.

Common Beginner Confusions Cleared

  • /proc files are not real files
  • lsmod is just a viewer, not a controller
  • Character drivers are not optional in kernel learning
  • Cleanup is as important as initialization

Final Thoughts

If modules programming basics is the foundation, then:

  • Character drivers are the walls
  • lsmod and /proc internals are the wiring behind them

Once you understand these:

  • Writing drivers becomes logical
  • Debugging becomes faster
  • Kernel code stops feeling dangerous

You are no longer guessing.
You are observing the kernel from the inside.

FAQ : Modules Programming Basics

1. What is a Linux kernel module (LKM)?
A Linux kernel module is a piece of code that can be loaded into or removed from the Linux kernel at runtime. It extends the kernel functionality without the need to reboot the system.

2. Why should I learn Linux kernel modules?
Learning LKMs allows you to write device drivers, implement new system features, or optimize kernel behavior. It’s essential for embedded systems, OS development, and low-level programming.

3. How do I create a Linux kernel module?
You write a C file containing init and exit functions, compile it with the kernel build system, and use insmod to load it and rmmod to remove it.

4. What are the key functions in a kernel module?
Every kernel module has at least:

  • init_module() or module_init() – runs when the module is loaded
  • cleanup_module() or module_exit() – runs when the module is removed

5. How do I check if a kernel module is loaded?
Use the command:

lsmod

It lists all currently loaded kernel modules.

6. What is modprobe and how is it different from insmod?

  • insmod loads a module manually
  • modprobe automatically handles module dependencies before loading

7. Can I pass parameters to a kernel module?
Yes, you can pass parameters using module_param() macros. For example, you can set buffer sizes, device IDs, or debugging flags at load time.

8. How do kernel modules help with device drivers?
Modules allow drivers to be loaded only when hardware is present, reducing memory usage and keeping the kernel modular and efficient.

9. What are kernel module dependencies?
Some modules require other modules to work. modprobe automatically loads dependencies, while insmod requires manual handling.

10. How do I debug Linux kernel modules?
You can use:

  • dmesg for kernel messages
  • printk() to print debug info from your module
  • Kernel debuggers like kgdb for advanced debugging

11. Can I update a module without rebooting Linux?
Yes, one of the main advantages of LKMs is hot-swapping – you can remove and reload updated modules without restarting the system.

12. What are the best practices for writing kernel modules?

  • Keep modules small and focused
  • Check return values and handle errors
  • Avoid blocking operations in the kernel
  • Use proper synchronization for shared resources

13. Which tools do I need to work with Linux kernel modules?

  • GCC compiler for C
  • Makefile for kernel build system
  • insmod, rmmod, modprobe, lsmod, and dmesg commands

14. Are Linux kernel modules secure?
Modules run in kernel space, so a buggy or malicious module can crash or compromise the system. Always validate code and test in a safe environment.

Read More about Process : What is is Process

Read More about System Call in Linux : What is System call

Read More about IPC : What is IPC

Leave a Comment

Exit mobile version