Writing your first Linux kernel module

Hello!

This post is going to cover how you can build and run your first kernel module.

Pre-requisites:

  1. Basic C Programming
  2. A bit of what kernel is

What is a module?

  • component that can be loaded and unloaded from an already running kernel
  • relocatable object file
  • .ko extension
  • has all potential as that of any other part of kernel once loaded

Let’s start writing the C program. Easy way to remember the header files to be included: Since you have to write a module for the linux kernel, start with including the file module.h from linux. Next, you need to initialize the module so include the file init.h from linux.
So far, you should reach to the following state:

#include <linux/module.h>
#include <linux/init.h>

Now, in order to load a module into the kernel, you should initialize the process, do that by making a call to module_init() macro. Also, for cleanup after unloading the module, make a call to module_exit() macro [Note: Cleanup function  is necessary as a module without it cannot be unloaded].

These macros are automatically called when the module is loaded or unloaded.

These macros can be brought into action by adding __init or __exit attributes as labels to our functions.
Simply put, the code for loading and unloading a module should look something like below:

static int __init demo_init(void)
{
        pr_info("Hello World! I'm loaded at 0x%p.\n", demo_init);
        return 0;
}
static void __exit demo_exit(void)
{
        pr_info("Goodbye, people! I'm unloading from 0x%p.\n", demo_exit);
}

Here, pr_info is printk function with the priority KERN_INFO.

The module looks pretty good, right? You’ve covered everything except having registered the init and exit functions. You can do that as follows:

module_init(demo_init);
module_exit(demo_exit);

All done now. From any programmer’s perspective the code should run now. Wait, there’s something kind of important while writing the linux kernel modules. Hint: Richard Stallman.

Yes! License. Your kernel module does not have any license. How do you add up a license? As simple as:

MODULE_LICENSE("GPL v2");

What happens when you don’t add up a license?

This.

CekKwYvXIAIaKhJ

Literally. Your module will be marked as tainted and will have a restricted API for interacting with rest of the kernel. Let’s not forget the love ( 😛 ) you might receive asking for help from kernel developers.

There is also a way to mark yourself the author if you’ve written a module. You do it by:

MODULE_AUTHOR("MOJO JOJO");

Who won’t want to add up this line, right?

Congratulations on having written your first linux kernel module. Now, let’s check if it is all correct.

Compilation

Pre-requisites:

  • kernel source installed (found under /lib/modules/$(uname -r)/build/)

[Tip: Make sure your kernel source has either been compiled before or has been through

$ make modules_prepare

stage. This is the way necessary configuration and dependency information is generated.]

Write Makefile for the module

If you named your module file say demo.c, then add up the following in Makefile:

obj-m += demo.o

Then, type:

$ make -C/lib/modules/$(uname -r)/build M=$(pwd) modules

Make sure to put the correct kernel sources with -C flag.

After this, your directory should contain files like below:

demo.c   demo.mod.c  demo.o    modules.order
demo.ko  demo.mod.o  Makefile  Module.symvers

To make the output verbose, set the environment variables as follows:

$ export KBUILD_VERBOSE=1

or

$ make V=1

 

Loading and unloading the modules

Now that the module has been built successfully, it is ready to be loaded into the kernel. For that, we use the following command:

$ sudo insmod demo.ko

insmod will link the module demo into the running kernel resolving all symbols.

This is exactly where the function with __init label is called.

In order to check if your module has been loaded, use

$ lsmod

This will give list of all loaded modules as per /proc/modules.

Your module will also show up like:

Module                  Size  Used by
demo                   16384  0

In order to see the output of your program, use:

$ dmesg

You should see:

[20564.992173] Hello World! I'm loaded at 0xffffffffc0018000.

In order to unload a module, you can use:

$ sudo rmmod demo

This is where the function with __exit label is called.

$ dmesg
[20707.254942] Goodbye, people! I'm unloading from 0xffffffffc0a69000.


Things to take care of

  • A module may depend on some other module(s) so the order of loading/unloading should be carefully done.
  • NOT ALL modules are device drivers, many of them are. 😉

Thanks for reading.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s