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 
#include

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 :
  • modprobe
  • insmod
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

This entry was posted in C Programming and tagged . Bookmark the permalink.