Tag: Makefile

  • Hello World Kernel Driver, Master How to Write in Linux (Step-by-Step Guide 2026)

    Hello World Kernel Driver : If you are starting your journey into Linux device driver development, writing a simple Hello World kernel module is the perfect first step. In this tutorial, we will walk you through creating, compiling, and loading a kernel driver in Linux — all in a beginner-friendly way.

    Learn how to write your first Hello World Linux kernel driver with this step-by-step tutorial for beginners. This complete Linux kernel module development guide covers everything from setting up your environment to compiling and loading a kernel module. You will understand the basics of Linux device driver development, including how to create a simple printk() output in the kernel log, use module_init and module_exit functions, and build your driver using a Makefile. Whether you’re new to kernel programming in Linux or want to get started with embedded systems and operating system internals, this beginner-friendly guide will help you master the fundamentals of writing and running your own kernel modules. Perfect for students, hobbyists, and professionals looking to learn Linux driver programming from scratch.

    What is a Hello World kernel module in Linux ?

    A Linux kernel module (LKM) is a piece of code that can be loaded and unloaded into the Linux kernel at runtime. This allows you to add new functionalities, such as hardware drivers, without rebuilding the entire kernel.

    A “Hello World” kernel driver is the simplest example — it just prints a message when loaded and unloaded.

    Prerequisites of Hello World Kernel Driver

    Before writing your kernel module, make sure you have:

    • A Linux system (Ubuntu, Debian, Fedora, or similar)
    • Basic knowledge of C programming
    • Installed kernel headers and build tools

    For Ubuntu/Debian-based systems, run:

    sudo apt update
    sudo apt install build-essential linux-headers-$(uname -r)
    

    Step 1: Create the Source Code

    Create a new directory for your driver and a file named hello.c:

    mkdir hello_driver
    cd hello_driver
    nano hello.c

    Paste the following code:

    #include <linux/init.h>     
    #include <linux/module.h>   
    #include <linux/kernel.h>   
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Your Name");
    MODULE_DESCRIPTION("A Simple Hello World Linux Kernel Module");
    MODULE_VERSION("1.0");
    
    static int __init hello_init(void) {
        printk(KERN_INFO "Hello, World! Kernel module loaded.\n");
        return 0;
    }
    
    static void __exit hello_exit(void) {
        printk(KERN_INFO "Goodbye, World! Kernel module unloaded.\n");
    }
    
    module_init(hello_init);
    module_exit(hello_exit);

    Explanation:

    • printk() prints messages to the kernel log (viewable with dmesg).
    • module_init() specifies the function to run when the module loads.
    • module_exit() specifies the function to run when the module unloads.

    Step 2: Create the Makefile

    The Makefile tells the Linux kernel build system how to compile your module.

    Create a file named Makefile:

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

    Step 3: Compile the Kernel Module

    Run:

    make

    If successful, you will see a new file called hello.ko — this is your compiled kernel driver.

    Step 4: Load the Module

    To load your driver into the kernel:

    sudo insmod hello.ko

    Check the kernel log:

    dmesg | tail

    You should see:

    Hello, World! Kernel module loaded.

    Step 5: Unload the Module

    When you want to remove the module:

    sudo rmmod hello

    Check the log again:

    dmesg | tail

    Output:

    Goodbye, World! Kernel module unloaded.

    Step 6: Clean Up

    To remove build files:

    make clean

    Final Thoughts

    You’ve just created your first Hello World kernel driver in Linux! This small example lays the foundation for developing more advanced Linux device drivers. From here, you can explore working with hardware, file operations, and different driver types (character, block, and network drivers)

    Frequently Asked Questions (FAQ) | Hello World Linux Kernel Driver

    1. What is a Hello World Kernel Driver ?

    A Linux kernel driver, also called a kernel module, is a piece of code that runs in the kernel space of the Linux operating system. It allows you to add functionalities like hardware control, system calls, or device communication without rebuilding the entire kernel.

    2. What is the purpose of a Hello World kernel module?

    The Hello World kernel module is the simplest example used to demonstrate Linux driver development. It helps beginners understand how to load and unload kernel modules, print messages to the kernel log, and use essential kernel functions.

    3. Do I need special hardware to write a Hello World Linux kernel driver?

    No. You can write and test a Hello World kernel module on any Linux system, including virtual machines, without special hardware.

    4. How do I compile a Hello World kernel module?

    You can compile a kernel module using a Makefile and the Linux kernel build system. The make command with the correct -C /lib/modules/$(uname -r)/build path will generate the .ko file (kernel object file) for your module.

    5. How do I load a kernel driver in Linux?

    You can load a compiled kernel driver using the insmod command, for example:
    sudo insmod hello.ko
    To confirm it loaded successfully, check the kernel log using:
    dmesg | tail

    6. How do I remove a kernel driver in Linux?

    You can remove a kernel driver using the rmmod command:
    sudo rmmod hello
    Then, verify it was removed by checking the kernel log with dmesg.

    7. Is it safe to experiment with kernel programming?

    Kernel programming requires caution because faulty code can crash the system. However, starting with a simple Hello World module in a test environment or virtual machine is safe and recommended for beginners.

    8. Can I use this Hello World driver on any Linux distribution?

    Yes, as long as your distribution provides the required kernel headers and build tools, you can compile and run the Hello World kernel module on Ubuntu, Debian, Fedora, Arch Linux, and more.
  • Master Build Process in C from Source Code to Executable (2026)

    Master the Build Process in C from source code to executable. Learn preprocessing, compilation, assembly, and linking for 2025 interviews.

    Master the Build Process in C from source code to executable in this complete 2025 guide. Learn each stage of the Build Process including preprocessing, compilation, assembly, and linking with clear explanations and real interview-oriented insights. Understand how source files are transformed into object files and finally into an executable, along with the role of compilers, assemblers, linkers, and build tools like GCC and Make. This guide is perfect for beginners, embedded engineers, and interview preparation, helping you troubleshoot build errors, optimize builds, and gain a strong foundation in C programming internals. Boost your understanding of the Build Process and confidently answer C interview questions in 2025.

    Build Process in C from ource Code to Executable : Understanding the build process in C is crucial for developers, especially those working with embedded systems, operating systems, or performance-critical applications. The process of transforming human-readable C source code into an executable involves multiple stages. Let’s dive deep into these stages and understand their significance.

    Stages of the Build Process

    The C build process consists of the following major stages:

    • Preprocessing
    • Compilation
    • Assembly
    • Linking

    Each of these stages plays a vital role in generating the final executable file.

    1. Preprocessing (Expanding Macros and Includes)

    The first stage of the build process is preprocessing, where the C preprocessor (cpp) expands macros, processes #include files, and handles conditional compilation directives like #ifdef.

    Key Tasks in Preprocessing:

    • Expands macros (#define)
    • Replaces header file includes (#include)
    • Handles conditional compilation (#ifdef, #ifndef, #endif)

    Example:
    Consider the following program.c:

    #include <stdio.h>  
    #define PI 3.14  
    int main() {  
        printf(\"Value of PI: %f\\n\", PI);  
        return 0;  
    }
    

    After preprocessing, the code will look like this:

    // Expanded version after preprocessing  
    #include <stdio.h>  
    int main() {  
        printf(\"Value of PI: %f\\n\", 3.14);  
        return 0;  
    }
    

    To see the preprocessed output, use:

    gcc -E program.c -o program.i  
    

    2. Compilation (Converting C Code to Assembly)

    In this stage, the compiler (gcc, clang) translates the preprocessed source code into assembly language, which is a low-level representation of the code.

    Example:

    gcc -S program.i -o program.s  
    

    This generates an assembly file (program.s) containing processor-specific instructions.

    Example assembly output (simplified):

    .section .text  
    .globl main  
    main:  
        pushq   %rbp  
        movq    %rsp, %rbp  
        movl    $0, %eax  
        popq    %rbp  
        ret  
    

    3. Assembly (Converting Assembly to Machine Code)

    The assembler (as) takes the assembly code and converts it into machine code, producing an object file (.o file).

    Command to generate object file:

    gcc -c program.s -o program.o  
    

    The .o file contains binary instructions but is not yet a complete executable because it still needs linking.

    4. Linking (Combining Object Files to Create an Executable)

    The linker (ld) combines multiple object files and links necessary system libraries to produce the final executable.

    • Resolves function calls (e.g., linking printf() to libc).
    • Merges object files (.o) into a single executable.
    • Allocates memory for variables and functions.

    Command to link:

    gcc program.o -o program  
    

    After linking, the final executable (program) is created and ready to run:

    ./program  
    

    Complete Build Process in One Command

    Instead of running all steps separately, we can compile and link in one step using:

    gcc program.c -o program  
    

    This internally performs preprocessing → compilation → assembly → linking automatically.

    Understanding Static and Dynamic Linking

    Static Linking:

    • Includes all required libraries in the executable.
    • Larger file size but runs independently.
    • Example: gcc -static program.c -o program

    Dynamic Linking:

    • Links external libraries at runtime (e.g., glibc).
    • Smaller executable but requires shared libraries (.so files).
    • Example: gcc program.c -o program -lm # Links math library dynamically

    Build Automation with Makefiles

    For large projects with multiple files, Makefiles automate the build process efficiently.

    Example Makefile:

    program: main.o helper.o  
        gcc main.o helper.o -o program  
    main.o: main.c  
        gcc -c main.c  
    helper.o: helper.c  
        gcc -c helper.c  
    clean:  
        rm -f *.o program  
    

    To build the program, simply run:

    make  
    

    To clean object files:

    make clean  

    💛 Support Embedded Prep

    If you find our tutorials helpful and want to support our mission of sharing high-quality embedded system knowledge, you can contribute by buying us a coffee. Every small contribution helps us keep creating valuable content for learners like you. ☕

    Thank you for your support — it truly keeps Embedded Prep growing. 💻✨

    Interview Questions of build process

    Build Process Basics

    1. What are the steps involved in the build process of a C/C++ program?
    2. What is the difference between compilation and linking?
    3. What happens during preprocessing? Can you give examples of preprocessing directives?
    4. What is an object file?
    5. Why do we need a linker in the build process?

    Makefile and Build Automation

    1. What is a Makefile and why is it used?
    2. Explain the structure of a Makefile. What are targets, prerequisites, and commands?
    3. How does make know when to rebuild a file?
    4. What is the difference between make and cmake?
    5. What is a phony target in Makefile and why do we use .PHONY?

    Toolchain and Cross-Compilation

    1. What is a cross-compiler and when do you use it?
    2. What’s the difference between gcc and g++?
    3. What are the different stages involved when using a cross-toolchain for embedded development?
    4. How do you build an image for an embedded board using a build system like Yocto or Buildroot?

    Build Configuration and Optimization

    1. What are common compiler optimization flags you use?
    2. What’s the purpose of flags like -Wall, -O2, -g, -std=c99, etc.?
    3. What’s the difference between static and dynamic linking?
    4. How do you debug a build error due to a missing symbol or header file?

    Advanced / Real-World Scenarios

    1. Have you written a custom Makefile or modified a Yocto recipe? Explain.
    2. How do you include third-party libraries in your build process?
    3. Have you used build systems like Yocto, CMake, or Bazel? Compare them.
    4. What’s the role of the linker script in embedded systems?

    Conclusion

    Understanding the build process helps in optimizing code, debugging errors, and improving performance. Whether you\’re debugging linking errors, reducing compilation time, or managing dependencies in large projects, mastering these stages is essential for any C developer.

    Thank you for exploring Build Process in C ! Stay ahead in embedded systems with expert insights, hands-on projects, and in-depth guides. Follow Embedded Prep for the latest trends, best practices, and step-by-step tutorials to enhance your expertise. Keep learning, keep innovating!

    You can also Visit other tutorials of Embedded Prep