Tag: kernel module basics

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

    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