Kernel module development can be challenging. Let’s write our first simple Linux Kernel Module.
Let’s create a directory:
mkdir blog-hello-world-kernel
Place a Makefile in that directory:
obj-m += bloghello.o
PWD := $(CURDIR)
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Place a simple C file:
bloghello.c
#include <linux/init.h>
#include <linux/module.h>
static int __init construct(void) {
pr_info("First kernel module: Hello World!\n");
return 0;
}
static void __exit destruct(void) {
pr_info("First kernel module has been removed\n");
}
module_init(construct);
module_exit(destruct);
MODULE_LICENSE("GPL");
Let’s build it:
root@main:~/blog-hello-world-kernel# make
make -C /lib/modules/5.11.0-49-generic/build M=/root/blog-hello-world-kernel modules
make[1]: Entering directory '/usr/src/linux-headers-5.11.0-49-generic'
CC [M] /root/blog-hello-world-kernel/bloghello.o
MODPOST /root/blog-hello-world-kernel/Module.symvers
CC [M] /root/blog-hello-world-kernel/bloghello.mod.o
LD [M] /root/blog-hello-world-kernel/bloghello.ko
BTF [M] /root/blog-hello-world-kernel/bloghello.ko
Skipping BTF generation for /root/blog-hello-world-kernel/bloghello.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-5.11.0-49-generic'
root@main:~/blog-hello-world-kernel#
The loadable kernel object has been created:
You can install the Kernel Object via the insmod
command:
insmod bloghello.ko
You can check if it is actually installed via lsmod
:
You can see the module’s output in /var/log/syslog
or in the output of dmesg
:
You can uninstall the module via rmmod
:
rmmod bloghello
Let’s check dmesg once more:
Congratulations! You’ve managed to construct your first Linux Kernel module.
You can print messages to different log levels:
#include <linux/init.h>
#include <linux/module.h>
static int __init construct(void) {
printk(KERN_INFO "INFO Level message\n");
pr_info("Another INFO Level message\n");
printk(KERN_WARNING "WARNING Level message\n");
pr_warn("Another WARNING Level message\n");
printk(KERN_ERR "ERROR Level message\n");
pr_err("Another ERROR Level message\n");
printk(KERN_CONT "This " );
pr_cont("message ");
printk(KERN_CONT "is " );
pr_cont("single ");
printk(KERN_CONT "line\n");
return 0;
}
static void __exit destruct(void) {
printk(KERN_INFO "The module has been removed\n");
}
module_init(construct);
module_exit(destruct);
MODULE_LICENSE("GPL");
Let’s check dmesg
:
You can filter log lines by levels: