— lkmp, linux, kernel — 4 min read
Yohooooo people!
Today we'll learn how to greet hoomans from Linux Kernel :P, i.e we'll learned how to write "Hello World!" Kernel Module \o/
We'll directly jump into the action and I'll explain what's happening in the later sections :)
1. Prepare your cauldron for the magical experiment
1mkdir hello-world2cd hello-world
2. Let's put our spells into the cauldron
1vim hello-world.c
Add the following into the hello-world.c
file.
1/*2 * hello_world.c -- A Kernel Module that prints Hello World3 */4#include<linux/init.h>5#include<linux/module.h>6
7// This function is executed when you load the module using insmod8static int __init helloworld_init(void)9{10 printk(KERN_INFO KBUILD_MODNAME ": Hello Confused Hooman!! \n");11 /*12 * A non 0 return means that module can't be loaded.13 */14 return 0;15
16}17
18static void __exit helloworld_cleanup(void)19{20 printk(KERN_INFO KBUILD_MODNAME ": Sayonara Hooman. \n");21}22
23// Register the module24module_init(helloworld_init);25module_exit(helloworld_cleanup);26
27// Information Regarding the module28MODULE_LICENSE("GPL");29MODULE_AUTHOR("Naveen Naidu");30MODULE_DESCRIPTION("A Hello World Kernel Module");
3. Create a new spell which will invoke the magic
1vim Makefile
Time for creating the new spell
1obj-m := hello_world.o2KDIR := /lib/modules/$(shell uname -r)/build3
4all:5 $(MAKE) -C $(KDIR) M=$(PWD) modules6
7clean:8 $(MAKE) -C $(KDIR) M=$(PWD) clean
4. Speak the new spell
1make all
5. Time to see the magic in action
1# Add the kernel module2sudo insmod hello_world.ko 3sudo dmesg -t -l info > dmesg_current_info 4
5# Time to see hello world message6cat dmesg_current_info | grep "hello"7
8# Remove the module and see if the module say's Byee9sudo rmmod hello_world.ko10sudo dmesg -t -l info > dmesg_current_info 11
12# See the Goodbye message from our module13cat dmesg_current_info | grep "hello"
TADA!! you have written your first Kernel module \o/ \o/
Note: For the folks who don't wanna try it out on your system but still wanna feast on the magic :P, I prepared an asciinema for you. Have a look at asciinema
These are the type of code that could be loaded and unloaded into the kernel on demand. This helps in extending the functionality of the kernel without the need to reboot the system.
Without the functionality of Kernel modules the only way we could have added new code was by statically linking it to the kernel that would mean, building the kernel after making any change. This would have had a very adverse impact on the development time of new features.
Having Kernel Modules also helps in easy debugging of the issues in a module instead of panicking the Kernel and crashing it.
A kernel module must have at least two functions:
The Initialization function is called whenever the kernel is loaded or whenever it is insmoded and the “end”/cleanup function is called whenever we unload/rmmod the module.
Though the first google results directed me to the page where the init_module()
function was used, but while browsing through the kernel code these functions
were rarely used and further reading I realized that I need not name my
functions as init_module()
or cleanup_module
mandatorily.
With the Kernel 2.4, I could use module_init()
and module_exit()
to name
the Initialization function and the ending function.
In order to print/log information from inside the kernel we use a function called “printk()”. The format of it is as follows:
1printk( <LOG LEVEL> <MORE OPTIONS> "Message String");
There is also a improved version of “printk()” which is “prinfo()” or “pr*” variants. For the sake of this task, I chose to use the “printk()” since it suited well for the needs of the task.
The logs/messages from the printk() is stored/logged in the /var/log/kern.log
and could easily be accessed using dmesg.
For the sake of the task, I chose to use the KERN_INFO
log level.
There are two kinds of kernel modules:
The way we build these two modules are slightly different but the gist says the same.
The following information is gathered after reading through the documentation in Documentation/kbuild/modules.rst. Though I was not able to comprehend everything present in the documentation (I hope someday with experience I could be able to do so :) but it was an interesting read and helped me a lot with my task.
The main highlights/important points for this is:
Create a local makefile where we define a kbuild variable like below.
1obj-<X> := <module_name>.o
The <X>
stands for kbuild variable and X
takes one of the following values
X = n
, Do not compile the module X = y
, Compile the module and statically link with kernel image X = m
, Compile the module as a dynamically loadable kernel moduleThe above line is enough for the Makefile, but we can also add additional make rules to make our life easy.
The command syntax for this is:
1make -C $KDIR M=$PWD [target]
KDIR
stands for the default kernel directory where the source is located.
M=$PWD
, this informs kbuild that an external module is being built. The value
that we give to the M is the absolute path where the external module (kbuild
file) is present.
To make our life easier we could combine the above two commands in our Makefile. For my Makefile, I have the following thing
1obj-m := hello_world.o 2KDIR := /lib/modules/$(shell uname -r)/build 3
4all: 5 $(MAKE) -C $(KDIR) M=$(PWD) modules 6clean: 7 $(MAKE) -C $(KDIR) M=$(PWD) clean
Thus when you run make all
, the kbuild system will build the hello_world.o
file from the hello_world.c
and after linking, will result in the kernel
module hello_world.ko
being created. And this will also install the module.
You can use the insmod
command to the .ko
file that is created after the
make command. This will load the module. If you want to see if the module is
loaded you could use the lsmod
command.
For example in my case:
1sudo insmod hello_world.ko2sudo lsmod | grep "hello"
Use the rmmod
command to unload the module.
For example in my case:
1sudo rmmod hello_world.ko2sudo lsmod | grep "hello"
That's the end of this post folks!!
Sayonara :3