Skip to content
Related Articles

Related Articles

Loadable Kernel Module – Linux Device Driver Development

Improve Article
Save Article
  • Last Updated : 18 Mar, 2022
Improve Article
Save Article

For Linux device drivers, we can use only two languages: Assembler and C. Assembler implements the main parts of the Linux kernel, while C implements the architecture-dependent parts. Uploaded kernel modules are often referred to as kernel modules or modules, but those are misleading names because there are so many types of modules in the world, and the various pieces built into the base kernel can easily be called modules. We use the term kernel module or LKM for certain types of modules that HOWTO refers to. Some people think of LKM as outside the kernel. They talk about LKMs that connect to the kernel. This is a mistake; LKM (if loaded) is a large part of the kernel. The correct term for the part of the kernel tied to the image you are launching, i.e. the whole kernel except LKMs, is “base kernel.” LKM connects to the base kernel. Let’s start writing a Loadable Kernel Module for Linux with the evergreen start program – The ” Hello -World “.

To Know More about Loadable Kernel Modules, Visit linux loadable kernel module

Step 1: Write the Code

Sample File: Learn. c 

C




#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_VERSION("4.15.0-133-generic");
static int __init start(void)
{
    printk(KERN_INFO "Loading module....");
    printk(KERN_INFO "Hello World....");
    return 0;
}
  
static void __exit end(void)
{
    printk(KERN_INFO "Bye World....");
}
module_init(start);
module_exit(end);


Fig 1.1 Learn.c File

Description : 

The my_init function is the driver initialization entry point and is called during system startup (if the driver is statically compiled into the kernel) or when the module is inserted into the kernel. The my_exit function is the driver exit point. It’s called when unloading a module from the Linux kernel. This function has no effect if the driver is statically compiled into the kernel. These functions are declared in the linux/module.h header file. 

Step 2: Building the Kernel Module

In modern kernel versions, the Makefile takes care of most of the building for developers. It starts the kernel build system and provides a list of components required to build the module. We are Giving the build path of the kernel version and it generates .ko and other files. This Kernel Object (KO) file generated will not be loaded into the Kernel.

Sample MakeFile

obj-m += learn.o
all:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

 Fig 1.2 A Simple Makefile

Fig 1.3 – After running the make command

Fig 1.4 – After Make command, we see the object file is generated

Step  3: insmod and rmmod

To load the module, we have to execute the insmod command from the source file folder. After this, the name of the driver is added to the /proc/modules file, while the device that the module registers is added to the /proc/devices file. Then we need to create the special character file for our major number with the mknod /dev/simple-driver c  250 0 commands. After we’ve created the device file, we need to perform the final verification to make sure that what we’ve done works as expected. To verify, we can use the cat or dmesg to see the messages command to display the device file contents.

Sample Output logs

1) Inserting module and viewing the messages

ubuntu@ubuntu:~/Desktop/LKM$ sudo insmod learn.ko 

ubuntu@ubuntu:~/Desktop/LKM$ dmesg | tail -10 

[ 1179.315828] audit: type=1400 audit(1645410095.127:35): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.hook.configure” pid=4520 comm=”apparmor_parser” 

[ 1181.044041] audit: type=1400 audit(1645410096.856:36): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.snap-store” pid=4521 comm=”apparmor_parser” 

[ 1182.803700] audit: type=1400 audit(1645410098.616:37): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.ubuntu-software” pid=4522 comm=”apparmor_parser” 

[ 1184.677654] audit: type=1400 audit(1645410100.492:38): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.ubuntu-software-local-file” pid=4526 comm=”apparmor_parser” 

[ 1282.734538] rfkill: input handler disabled 

[ 5315.486562] learn: module verification failed: signature and/or required key missing – tainting kernel 

[ 5315.486700] Loading module…. 

[ 5315.486702] Hello World….

Fig 1.5 – Logs after the module is inserted

2) Removing Module using rmmod command and exit function is invoked

ubuntu@ubuntu:~/Desktop/LKM$ sudo rmmod learn 

ubuntu@ubuntu:~/Desktop/LKM$ dmesg | tail -10 

[ 1181.044041] audit: type=1400 audit(1645410096.856:36): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.snap-store” pid=4521 comm=”apparmor_parser” 

[ 1182.803700] audit: type=1400 audit(1645410098.616:37): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.ubuntu-software” pid=4522 comm=”apparmor_parser” 

[ 1184.677654] audit: type=1400 audit(1645410100.492:38): apparmor=”STATUS” operation=”profile_replace” profile=”unconfined” name=”snap.snap-store.ubuntu-software-local-file” pid=4526 comm=”apparmor_parser” 

[ 1282.734538] rfkill: input handler disabled [ 5315.486562] learn: module verification failed: signature and/or required key missing – tainting kernel 

[ 5315.486700] Loading module…. 

[ 5315.486702] Hello World…. 

[ 5340.195459] Bye World….

Fig 1.5 – Logs after the module is inserted


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!