Writing First Linux kernel Module

We will try to understand the simple kernel driver, its compilation and ways to load the kernel module in running Linux system. This post describes more onto practical than theoretical understanding of each and every API used by driver. So, you should be able to copy the code as is and get your first kernel module working.

The steps are done on Ubuntu Linux, those should work as is on any other Linux distribution as well.

$ mkdir module_workspace 
$ cd module_workspace 
 $ vim hello.c 
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */

static int __init hello_init(void) {
    printk(KERN_INFO "Hello, world\n");
    return 0;
}

static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye, world\n");
}

module_init(hello_init);
module_exit(hello_exit);

Create a Makefile,

$ vim Makefile
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

[Note: Make sure you have added TAB before “make” in above makefile ]

Now, compile this kernel module for Ubuntu based host,

$ make
make -C /lib/modules/5.4.0-90-generic/build M=/home/devlab/devlab/kernel_module modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-90-generic'
  CC [M]  /home/devlab/devlab/kernel_module/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
WARNING: modpost: missing MODULE_LICENSE() in /home/devlab/devlab/kernel_module/hello.o
see include/linux/module.h for more information
  CC [M]  /home/devlab/devlab/kernel_module/hello.mod.o
  LD [M]  /home/devlab/devlab/kernel_module/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-90-generic'
$ ls
hello.c  hello.ko  hello.mod  hello.mod.c  hello.mod.o  hello.o  Makefile  modules.order  Module.symvers
$ file hello.ko
hello.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=b233f3be8ee0cf063554188edfb6f62eca370c0e, not stripped
$ tree
.
├── hello.c
├── hello.ko
├── hello.mod
├── hello.mod.c
├── hello.mod.o
├── hello.o
├── Makefile
├── modules.order
└── Module.symvers

The “tree” command shows the output files generated during compilation process. Now, we will try to insert that module to kernel as,

$ sudo insmod ./hello.ko

Notice, the error if any, now you can check if the module is successfully inserted to the system,

$ dmesg
[ 2260.748252] hello: module license 'unspecified' taints kernel.
[ 2260.748261] Disabling lock debugging due to kernel taint
[ 2260.748315] hello: module verification failed: signature and/or required key missing - tainting kernel
[ 2260.748790] Hello, world
$ lsmod | grep hello
hello 16384 0

Notice that the module has been inserted into the system with some license warning, which we will try to understand ahead, lsmod shows the list of modules running.

Now, lets try to remove this module from kernel as below,

$ sudo rmmod hello
$ dmesg
[ 3026.031566] Goodbye, world

above dmesg command shows, rmmod command called “module_exit” from our driver and displayed the message.

Here, in above code we had got th e following warning,

$ dmesg
[ 2260.748252] hello: module license 'unspecified' taints kernel.
[ 2260.748261] Disabling lock debugging due to kernel taint
[ 2260.748315] hello: module verification failed: signature and/or required key missing - tainting kernel

This was due to missing LICENSE, so we added the following lines at the end of kernel module hello.c

MODULE_AUTHOR("DEVBEE");
MODULE_DESCRIPTION("Hello World Example");
MODULE_LICENSE("GPL");

Which will remove this warning.

$ make 
$ sudo insmod ./hello.ko 
$ dmesg
[ 4051.863842] Hello, world

In UEFI enabled laptops/desktops, we will not be able to insert the kernel module immediately as we did here, so please follow the signing steps as mentioned in “How to sign kernel module on UEFI Secure boot enabled Ubuntu ?

In our next post, we will try to understand “Passing command line Arguments / Parameters to Linux kernel module

1 thought on “Writing First Linux kernel Module”

Leave a Comment