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.
Comments on this entry are closed.
Hello Himanshu,
Great topic, neat and clear.
However, is this one tiny april fool?
How could kernel log those strings:
“Hello world!!!!!” and “Goodbye world!!!!!!”
when source code contains:
“Welcome…..\n” and “Bye….\n”
— Philippe
Very interesting article !!
Thank you for this introduction.
I want just mention a new way to maintain kernel module use what is called DKMS.
https://en.wikipedia.org/wiki/Dynamic_Kernel_Module_Support
Which may help new comers.
Good article. Thanks.
[ 4048.333756] Hello world!!!!!. ==> Welcome…..
[ 4084.205143] Goodbye world!!!!!!. ==> Bye….
🙂
might want to specify the filename of the src file used to create the loadable module. Also, instead of a makefile, break down the steps into individual calls (e.g. gcc, etc), so we can clearly see what is going on. Makefiles tend to make it difficult to see what is going on with all the variables.
Regardless, it is a very good article.
the contents of src file and example output do not match. It should print “Welcome…” and “Bye…” respectively. Please fix.
Where did the test Hello world and good bye world originate?
@All,
Thanks for pointing out the issue. It is fixed now. The log should contain the following:
@All
Sorry for a little goof up related to logs. It has been fixed now.
@bob
Thanks for your suggestion. I’l try to incorporate it in my future articles.
thanks.
thanks
Thank you
If i unload the LKM, means i got following error message.
ERROR: Removing ‘try1’: Device or resource busy.
and also this module permentle stored,see following
Module Size Used by
try1 12426 0 [permanent]
Why sudo used in makefile pls explain these….?