The Linux kernel is a free and open-source project that is similar to the Unix-like operating systems. The Linux kernel was created by Linus Torvalds in 1991.
The Linux kernel manages system resources, creates and destroys processes, manages memory, and provides communication between software and hardware, such as CPU, memory, and I/O devices, etc.
One of the great features of the Linux kernel is its ability to support the loading/unloading of kernel modules. It could be drivers or modules which can be loaded and unloaded at runtime, without the need to reboot the system. Writing your first kernel module can be an exciting and rewarding experience.
Before you start writing your first kernel module, you need to make sure that you have a kernel development environment. This typically involves installing a set of tools and libraries, including the kernel headers and development packages. Remember it could be different in other systems.
These examples have been done in Ubuntu 20.04 but it’s similar in other distributions.
$ sudo apt update && sudo apt upgrade
First, let’s update and upgrade the system
$ sudo apt-get install gcc make build-essential libncurses-dev exuberant-ctags build-essential linux-headers-`uname -r`
This will install the essential development tools and the kernel headers necessary for this example.
Once you have your development environment set up, you can begin writing your kernel module.
Here's a basic example of a kernel module that simply prints a message to the system log when it is loaded and unloaded, let's create a file hello.c and add the below content in there.
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int __init module_start(void)
{
printk(KERN_INFO "Hello, World!\n");
return 0;
}
static void __exit module_end(void)
{
printk(KERN_INFO "Goodbye, World!\n");
}
module_init(module_start);
module_exit(module_end);
#include <linux/init.h>: This line includes the header file for kernel initialization functions, which are needed to set up the module.
#include <linux/kernel.h>: This line includes the header file for kernel functions, which are needed to perform actions such as printing messages to the kernel log.
#include <linux/module.h>: This line includes the header file for kernel modules, which are used to add functionality to the kernel.
MODULE_LICENSE("GPL");: This line sets the license for the module to the GNU General Public License (GPL). This is required for all kernel modules.
static int __init module_start(void): This line defines the initialization function for the module, which will be called when the module is loaded into the kernel. The "__init" keyword tells the kernel to discard this function after it is called, to save memory.
printk(KERN_INFO "Hello, World!\n");: This line uses the printk() function to print the message "Hello, World!" to the kernel log, using the KERN_INFO priority level.
return 0;: This line returns 0 to indicate that the initialization function has been completed successfully.
static void __exit module_end(void): This line defines the cleanup function for the module, which will be called when the module is unloaded from the kernel. The "__exit" keyword tells the kernel to discard this function after it is called, to save memory.
printk(KERN_INFO "Goodbye, World!\n");: This line uses the printk() function to print the message "Goodbye, World!" to the kernel log, using the KERN_INFO priority level.
module_init(module_start);: This line registers the initialization function with the kernel, so that it will be called when the module is loaded.
module_exit(module_end);: This line registers the cleanup function with the kernel, so that it will be called when the module is unloaded.
To compile this module, you will need to create a Makefile that specifies the module name and source files.
Here's an example 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
This Makefile will build a kernel module named hello.o from the source file hello.c.
To build the module, simply run make in the directory containing the Makefile. If everything goes well, you should see a hello.ko file generated, which is the compiled kernel module. Also you can use make clean for clean directory and remove generated files
all: This line specifies a target called "all", which is the default target when no specific target is specified. The target "all" will build the kernel module.
clean: This line specifies a target called "clean", which will clean up any files created during the build process.
To load the module, use the insmodcommand:$ sudo insmod hello.ko
To unload the module, use the rmmodcommand:$ sudo rmmod hello.ko
You can check the system log using the dmesg command or check the /var/log/syslog log file to see the messages printed by the module:
$ dmesg | grep World
[566458.370280] Hello, World!
[566490.188611] Goodbye, World!
In conclusion, writing a Linux kernel module can be a challenging but rewarding experience. Kernel module development requires some basic understanding of the Linux operating system and command line, as well as some base knowledge of C programming language.
However, once you have mastered the basics, you can start programming Linux kernel modules and drivers which can be used for various spheres.
In this article, we have covered the essential steps required to create a simple "Hello, World!" kernel module. We use Linux Ubuntu 20.04 and started by setting up the development environment by installing the necessary packages. Then, we explored the simple structure of a Linux kernel module.
We also compiled and loaded the basic module into the Kernel by using insmod command, and unload by using rmmod command.
What did you think of this guide? Please let me know in the comments below and follow me on HackerNoon for more guides like this!
The lead image for this article was generated with Kadinsky 2 on HackerNoon.
Prompt: Linux kernel holding kernels