How to Write Your Own Linux Kernel Module with a Simple Example

by Lakshmanan Ganapathy on July 17, 2013

What are kernel modules?

Kernel modules are piece of code, that can be loaded and unloaded from kernel on demand.

Kernel modules offers an easy way to extend the functionality of the base kernel without having to rebuild or recompile the kernel again. Most of the drivers are implemented as a Linux kernel modules. When those drivers are not needed, we can unload only that specific driver, which will reduce the kernel image size.

The kernel modules will have a .ko extension. On a normal linux system, the kernel modules will reside inside /lib/modules/<kernel_version>/kernel/ directory.

Earlier we discussed how to compile a kernel from the source.

This tutorial explains how to write a Kernel module using a simple Hello World example.

I. Utilities to Manipulate Kernel Modules

1. lsmod – List Modules that Loaded Already

lsmod command will list modules that are already loaded in the kernel as shown beblow.

# lsmod
Module                  Size  Used by
ppp_deflate            12806  0 
zlib_deflate           26445  1 ppp_deflate
bsd_comp               12785  0 
..

2. insmod – Insert Module into Kernel

insmod command will insert a new module into the kernel as shown below.

# insmod /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko

# lsmod | grep "squash"
squashfs               35834  0

3. modinfo – Display Module Info

modinfo command will display information about a kernel module as shown below.

# modinfo /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko

filename:       /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko
license:        GPL
author:         Phillip Lougher 
description:    squashfs 4.0, a compressed read-only filesystem
srcversion:     89B46A0667BD5F2494C4C72
depends:        
intree:         Y
vermagic:       3.5.0-19-generic SMP mod_unload modversions 686

4. rmmod – Remove Module from Kernel

rmmod command will remove a module from the kernel. You cannot remove a module which is already used by any program.

# rmmod squashfs.ko

5. modprobe – Add or Remove modules from the kernel

modprobe is an intelligent command which will load/unload modules based on the dependency between modules. Refer to modprobe commands for more detailed examples.

II. Write a Simple Hello World Kernel Module

1. Installing the linux headers

You need to install the linux-headers-.. first as shown below. Depending on your distro, use apt-get or yum.

# apt-get install build-essential linux-headers-$(uname -r)

2. Hello World Module Source Code

Next, create the following hello.c module in C programming language.

#include <linux/module.h>    // included for all kernel modules
#include <linux/kernel.h>    // included for KERN_INFO
#include <linux/init.h>      // included for __init and __exit macros

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lakshmanan");
MODULE_DESCRIPTION("A Simple Hello World module");

static int __init hello_init(void)
{
    printk(KERN_INFO "Hello world!\n");
    return 0;    // Non-zero return means that the module couldn't be loaded.
}

static void __exit hello_cleanup(void)
{
    printk(KERN_INFO "Cleaning up module.\n");
}

module_init(hello_init);
module_exit(hello_cleanup);

Warning: All kernel modules will operate on kernel space, a highly privileged mode. So be careful with what you write in a kernel module.

3. Create Makefile to Compile Kernel Module

The following makefile can be used to compile the above basic hello world kernel module.

obj-m += hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Use the make command to compile hello world kernel module as shown below.

# make

make -C /lib/modules/3.5.0-19-generic/build M=/home/lakshmanan/a modules
make[1]: Entering directory `/usr/src/linux-headers-3.5.0-19-generic'
  CC [M]  /home/lakshmanan/a/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/lakshmanan/a/hello.mod.o
  LD [M]  /home/lakshmanan/a/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-19-generic'

The above will create hello.ko file, which is our sample Kernel module.

4. Insert or Remove the Sample Kernel Module

Now that we have our hello.ko file, we can insert this module to the kernel by using insmod command as shown below.

# insmod hello.ko

# dmesg | tail -1
[ 8394.731865] Hello world!

# rmmod hello.ko

# dmesg | tail -1
[ 8707.989819] Cleaning up module.

When a module is inserted into the kernel, the module_init macro will be invoked, which will call the function hello_init. Similarly, when the module is removed with rmmod, module_exit macro will be invoked, which will call the hello_exit. Using dmesg command, we can see the output from the sample Kernel module.

Please note that printk is a function which is defined in kernel, and it behaves similar to the printf in the IO library. Remember that you cannot use any of the library functions from the kernel module.

Now you have learned the basics to create your own Linux Kernel module.


Linux Sysadmin Course Linux provides several powerful administrative tools and utilities which will help you to manage your systems effectively. If you don’t know what these tools are and how to use them, you could be spending lot of time trying to perform even the basic administrative tasks. The focus of this course is to help you understand system administration tools, which will help you to become an effective Linux system administrator.
Get the Linux Sysadmin Course Now!

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

{ 22 comments… read them below or add one }

1 Jalal Hajigholamali July 17, 2013 at 8:44 am

Hi,

Thanks.
Very useful article
Thanks again

2 prakash July 17, 2013 at 9:14 am

Very nice explaination

3 Andrew July 17, 2013 at 10:26 am

Good article, but one slight adjustment:

You suggest creating the file helloworld.c, but specify hello.o in the Makefile. My code wouldn’t compile because of this – I had to put “obj-m += helloworld.o” in the Makefile before it would work.

Once I figured that out, Bob’s your uncle, thanks for posting this.

4 Júlio Hoffimann Mendes July 17, 2013 at 10:39 am

Simply incredible article!

Thanks.

5 rmbs July 17, 2013 at 10:41 am

really very useful, your website it’s wonderful. i learning a lot. thanks

6 Bob July 17, 2013 at 10:51 am

Great article!!
One suggestion would be maybe a 1 paragraph to describe when you would write a kernel module vs running the same code in user space.

7 A.Baines July 17, 2013 at 10:52 am

This is great, all this geek stuff just keeps getting better. Thank you!

8 Mitra July 17, 2013 at 1:07 pm

Awesome article !! Thanks for sharing such stuff.

9 Satheesh Kumar July 17, 2013 at 9:55 pm

Superb explanation

10 Pawan Bahuguna July 17, 2013 at 11:13 pm

Thanks, looks useful.

11 Claudio July 22, 2013 at 2:03 pm

Great Article, but I have to agree with Bob. An explanation when you would write a kernel module instead of creating a program in user space would be a good idea.

12 Kushal July 23, 2013 at 12:21 am

Great…keep it up!!!!

13 Andy July 31, 2013 at 2:33 pm

I’ve tried on two Ubuntu boxes and both have build-essentials and linux-headers (linux-headers-2.6.32-45-generic) installed but no linux/module.h available. I can see it in /usr/src/linux-headers-2.6.32-45-generic/include/linux/module.h but …

14 Andy July 31, 2013 at 4:35 pm

Never mind, or, rather, I have a Makefile problem – running:
$ make -C /lib/modules/$(uname -r)/build M=${PWD} modules

works just fine.
Thanks.

15 Kiren Pillay August 1, 2013 at 5:15 am

Hi

Just make sure you have tabs in the makefile, or you’ll get
“make: Nothing to be done for `all’ ”

e.g
all:
make −C /lib/modules/$(shell uname −r)/build M=$(PWD) modules
clean:
make −C /lib/modules/$(shell uname −r)/build M=$(PWD) clean

16 raghu August 3, 2013 at 11:07 am

i am executing the make command on cent os i am getting error like

make -C /lib/modules/2.6.32-358.el6.i686/build M=/root modules
make: *** /lib/modules/2.6.32-358.el6.i686/build: No such file or directory. Stop.
make: *** [all] Error 2

any help ?

17 DEV September 15, 2013 at 1:59 am

Hi,thanks for the article. I have one doubt,while trying out various things I found that when I comment out module_init and module_exit, the code works fine still and the module gets loaded. But you have said those two are used to call the entry and exit funcs. HOW DID IT WORK THEN??

Also,I am not using init_module or cleanup_module(pre-defined ones..)

PLZ CLARIFY… :-)

18 Lakshmanan Ganapathy September 24, 2013 at 11:14 pm

@DEV

When you do insmod, the module will be loaded into kernel, but the entry function will not be called, and without that there is no use of a module. In my opinion, kernel module without module_init will be of no use.

Only when you do module_init, the entry function will be called, and the module can start performing its operations.

19 DEV September 25, 2013 at 2:29 am

Hi, yeah got it figured already when I looked for the logs… there was no entry without those two… Thanks. :-)

20 Bindesh Kumar Singh November 12, 2013 at 10:21 am

Nice article,

but it needs “shell uname” changed “uname”, and $(PWD) to `pwd`. Because PWD may not have been set by user in shell.

above suggestion is for doing compilation without makefile OR shell specific settings. As many users have posted about makefile doing nothing.

21 ajay February 17, 2014 at 6:44 am

Thanx. It helped !

22 shruthi nd April 18, 2014 at 11:57 pm

how to clear the eror all is up to data.while running make i am getting this error plz help me how to solve this error……i am using 3.13.1 kernel version……while updating headres it giving some errors.how to clear these errors

Leave a Comment

Previous post:

Next post: