≡ Menu

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
        sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
        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
vermagic: 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.

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 12 comments… add one }

  • Philippe Petrinko April 2, 2012, 2:31 am

    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

  • Ashok April 2, 2012, 3:03 am

    Very interesting article !!

  • Abdellah Chelli April 2, 2012, 3:09 am

    Thank you for this introduction.

    I want just mention a new way to maintain kernel module use what is called DKMS.

    Which may help new comers.

  • Bhaskar April 2, 2012, 6:47 am

    Good article. Thanks.

    [ 4048.333756] Hello world!!!!!. ==> Welcome…..
    [ 4084.205143] Goodbye world!!!!!!. ==> Bye….


  • bob April 2, 2012, 6:55 am

    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.

  • george April 2, 2012, 11:06 am

    Where did the test Hello world and good bye world originate?

  • Ramesh Natarajan April 2, 2012, 6:54 pm


    Thanks for pointing out the issue. It is fixed now. The log should contain the following:

    [ 4048.333756] Welcome.....
    [ 4084.205143] Bye....
  • Himanshu Arora April 3, 2012, 5:31 am

    Sorry for a little goof up related to logs. It has been fixed now.

    Thanks for your suggestion. I’l try to incorporate it in my future articles.

  • mahyar May 1, 2012, 2:38 am


  • Micheal January 29, 2013, 12:39 am


  • Sunil February 27, 2013, 5:22 am

    Thank you

  • Rahul July 1, 2014, 12:28 am

    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….?

Leave a Comment