Linux Kernel Module Basics

The codes on the post are from the Linux kernel module programming guide 1.

A Linux kernel module is a piece of compiled binary code that is inserted directly into the Linux kernel 2. The important kernel module commands are as follows:

  • insmod: Install a module
  • rmmod: Remove a module
  • lsmod: Show status of loaded modules by reading /proc/modules
  • modprobe: Add/remove modules from the kernel (consider dependency)
  • depmod: Generate modules.dep and map files

Now let’s start playing with some kernel modules!

// m_hello_1.c
#include <linux/module.h> // for kernel module
#include <linux/kernel.h> // for KERN_INFO

int init_module(void) {
	printk(KERN_INFO "Hello world 1\n");
	return 0; // init_module module succeeded
}

void cleanup_module(void) {
	printk(KERN_INFO "Goodbye world 1\n");
}

This is old style kernel module. init_module() is called when the module is loaded (by executing insmod), and cleanup_module() is called when the module is removed (by executing rmmod). A Makefile for the source code is as follows.

obj-m += m_hello_1.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

After writing Makefile, I can generate m_hello_1.ko by running make (run make clean to remove it).

Installing and removing m_hello_1 module is done by running insmod and rmmod.

shnoh@shnoh-p6-2270kr:~/kmod$ sudo insmod m_hello_1.ko
shnoh@shnoh-p6-2270kr:~/kmod$ dmesg | grep Hello
[6000342.646421] Hello world 1

shnoh@shnoh-p6-2270kr:~/kmod$ sudo rmmod m_hello_1
shnoh@shnoh-p6-2270kr:~/kmod$ dmesg | grep Goodbye
[6000365.592283] Goodbye world 1

We can rename init_module() and cleanup_module() using __init and __exit macros, respectively. The code is shown in m_hello_2.c.

#include <linux/module.h> // for kernel module
#include <linux/kernel.h> // for KERN_INFO
#include <linux/init.h> // for macros

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

static void __exit hello_2_exit(void)
{
	printk(KERN_INFO "Goodbye world 2\n");
}

module_init(hello_2_init);
module_exit(hello_2_exit)

Building, installing and removing the module m_hello_2 are as same as m_hello_1.

In m_hello_3, I added __initdata which is only used in the initialization process. Also, I added license and driver information.

#include <linux/module.h> // for kernel module
#include <linux/kernel.h> // for KERN_INFO
#include <linux/init.h> // for macros

#define DRIVER_AUTHOR "Soonhyun Noh <xxxxx@redwood.snu.ac.kr>"
#define DRIVER_DESC "Sample driver"

static int hello3_data __initdata = 3;

static int __init hello_3_init(void)
{
	printk(KERN_INFO "Hello world %d\n", hello3_data);
	return 0;
}

static void __exit hello_3_exit(void)
{
	printk(KERN_INFO "Goodbye world 3\n");
}

MODULE_LICENSE("GPL");

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);

module_init(hello_3_init);
module_exit(hello_3_exit);
  1. Peter Jay Salzman, Micheal Burian and Ori Pomerantz, “The Linux Kernel Module Programming Guide,” 2001. 

  2. https://blog.sourcerer.io/writing-a-simple-linux-kernel-module-d9dc3762c234 

Comments