How to Create, Compile, Load Linux LKM Loadable Kernel Modules
Suppose we want to add some extra functionality in the Linux kernel.
So the first idea that strikes the mind is to enhance the kernel by adding more code to it, compiling the code and getting the new kernel up.
But this process has the following drawbacks among several others:
- The added code adds to the size of kernel permanently.
- The whole kernel needs to be compiled again for the changes to get compiled.
- This means that machine needs to be rebooted for changes to take affect.
The solution to above problems is the concept of LKMs.
LKM stands for Loadable kernel modules (LKM). As the name suggests LKMs are the modules that can be directly loaded in kernel at run time.
The loadable kernel module overcomes all the above mentioned shortcomings.
- The module can be compiled separately
- The module can be loaded onto kernel at run time without having the machine to reboot.
- The module can be unloaded anytime and hence no permanent affect on kernel size.
How to Create LKMs
Lets create a basic loadable kernel module.
#include <linux/module.h> #include <linux/kernel.h> int init_module(void) { printk(KERN_INFO "Welcome.....\n"); return 0; } void cleanup_module(void) { printk(KERN_INFO "Bye....\n"); }
So we see that the above code is a basic LKM.
- The names ‘init_module’ and ‘cleanup_module’ are standard names for an LKM.
- If you see closely then you will find that we have used ‘printk’ instead of ‘printf’. This is because it is not a normal C programming, its a kernel level programming which is a bit different from normal user level programming.
- The headers module.h and kernel.h has to be included to get the code compiled.
How to Compile LKMs
To compile the above LKM, I used the following Makefile :
obj-m += lkm.o all: sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Note that the commands beginning with the keyword ‘sudo’ above should have one tab space from the left.
So, when the above command is run, the following output is observed :
make: Entering directory `/usr/src/linux-headers-2.6.32-21-generic' CC [M] /home/himanshu/practice/lkm.o Building modules, stage 2. MODPOST 1 modules CC /home/himanshu/practice/lkm.mod.o LD [M] /home/himanshu/practice/lkm.ko make: Leaving directory `/usr/src/linux-headers-2.6.32-21-generic'
After the above successful compilation you will find a .ko file in the same directory where the compilation took place.
This .ko file is the module that will be loaded in the kernel. modinfo utility can be used to fetch the information about this module :
$ modinfo lkm.ko filename: lkm.ko srcversion: 19967CB3EAB7B31E643E006 depends: vermagic: 2.6.32.11+drm33.2 SMP mod_unload modversions
So we see that the utility ‘modinfo’ provides some information about this module.
How LKM is Loaded
After a successful compilation and creation of the module, now is the time to insert it in the kernel so that it gets loaded on run time. The insertion of the module can be achieved using the following two utilities :
The difference between the two lies in the fact that ‘modprobe’ take care of the fact that if the module in dependent on some other module then that module is loaded first and then the main module is loaded. While the ‘insmod’ utility just inserts the module (whose name is specified) into the kernel.
So ‘modprobe’ is a better utility but since our module is not dependent on any other module so we will use ‘insmod’ only.
So, to insert the module, the following command is used :
$ sudo insmod ./lkm.ko
if this command does not give any error then that means the LKM is loaded successfully in the kernel.
To unload the LKM, the following command is used :
$ sudo rmmod lkm.ko
Again, if this command does not give any error then that means the LKM is un-loaded successfully in the kernel.
To check that the module was loaded and unloaded correctly we can use the dmesg utility which gives the last set of logs as logged by the kernel. You’ll see the following two lines among all the other logs :
.... .... [ 4048.333756] Welcome..... [ 4084.205143] Bye....
If you go back to the code and see then you will realize that these are the logs from the two functions in the code.
So we see that one function was called when the ‘insmod’ was called and the other function was called when the ‘rmmod’ was called.
This was just a dummy LKM. In this way many working LKM (that carry out meaningful tasks) work inside Linux kernel.