As I delved deeper into the world of Linux, I became fascinated by its core: the kernel. The kernel is the central component of the operating system that manages the system’s resources. One of the most powerful features of the Linux kernel is its ability to be extended with loadable modules. Writing a kernel module allows you to add functionality directly to the running kernel without needing to recompile the entire thing.
Table of Contents
While kernel programming can be incredibly complex, creating a simple “Hello, World!” module is a fantastic way to understand the basics. This guide will walk you through the C code and the Makefile I used to create and load my first kernel module.
📝 The C Code for the Module
A kernel module is a piece of C code that can be loaded into and unloaded from the kernel on demand. A minimal module needs at least two functions: an initialization function that is called when the module is loaded, and a cleanup function that is called when it’s removed.
Here is the basic structure:
“`c int init_module(void) void cleanup_module(void) I use `printk` instead of the standard `printf` because kernel modules cannot link to standard libraries. `printk` writes messages to the kernel log buffer, which I can view using the `dmesg` command. Compiling a kernel module is different from compiling a regular user-space program. It requires a special Makefile that knows how to use the kernel’s build system. The Makefile is surprisingly simple for a basic module: “`makefile all: clean: This tells the build system that I want to create a module from my `hello.c` file and points it to the correct kernel headers for my currently running kernel. With this Makefile in the same directory as my C file, I can compile the module by simply running the `make` command in my terminal. After a successful compilation, I have a new file called `hello.ko`—this is my kernel module. To load it into the kernel, I use the `insmod` command: `sudo insmod hello.ko`. Immediately after running this, I can check the kernel log for my message by running `dmesg`. I should see the “Hello, World!” message printed at the end of the log. To unload the module, I use the `rmmod` command: `sudo rmmod hello`. After this, running `dmesg` again will show my “Goodbye, World!” message. For those interested in system-level tasks, learning how to automate sysadmin tasks with Bash is another great skill to have.
#include
{
printk(KERN_INFO “Hello, World!\n”);
return 0;
}
{
printk(KERN_INFO “Goodbye, World!\n”);
}
“`🛠️ The Makefile for Compilation
obj-m += hello.o
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
“`🚀 Loading and Unloading the Module