Monday 19 May 2014

How to write a simple Kernel module

After a long break, I am starting this simple post on how to write a kernel module.

I will demonstrate with code, how to write a module that prints message on loading and unloading and nothing more. This will give a good hands on understanding the Makefile and kernel modules.

SOURCE

Consider the following simple .c file

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

#include<linux/stat.h>

MODULE_AUTHOR("GOMATHI KUMAR");
MODULE_LICENSE("GPL");

static int abc=5;
static char *name="sweets";
module_param(abc,int,S_IRUGO | S_IWUSR);

module_param(name,charp,S_IRUGO | S_IWUSR);

static int init_mod()
{
        printk(KERN_ERR "%s: %s : HI.. Good day...\nLoading your module\nabc = %d and name = %s\n", __FILE__, __FUNCTION__, abc, name);
        return 0;
}
static int exit_mod()
{
        printk(KERN_ERR "%s: %s : End of module\n\nBye! Bye!!\nabc = %d and name = %s\n", __FILE__, __FUNCTION__, abc, name);
        return 0;
}

module_init(init_mod);

module_exit(exit_mod);


This c file shows two simple functions that will be executed during init and exit of the module. 

Points to be considered in the above c file : 
a) Module_init and module_exit functions define which function is to be called during loading and unloading of the module
b) printk is the kernel function equivalent of printf that is used in user space. The printks can be used in different log levels such as KERN_ERR, KERN_WARN etc based on the level of importance. This can be used for kernel debugging, though using printk is not an efficient way of kernel debugging. 
c) __FILE__ and __FUNCTION__ are predefined macros, that will print the name of the file and function. There are other such macros, which will give useful information. 
d) The details that are displayed when we do modinfo is from MODULE_AUTHOR, MODULE_LICENSE etc that are defined in the above c file.
e) module_param will help in passing parameters to the module during runtime. This will create entries in sysfs as follows
/sys/module/<YOUR MODULE>/paramaeter/<MODULE_PARAM_YOU_DEFINED>
For the definition of module_param function, moduleparam.h has to be included.
The permissions for reading and writing can be controlled by the third parameter in module_param. The permissions S_IRUGO, S_IWUSR etc are defined in stat.h
Once write permission is given, we can change sysfs entry and from then on that value will be retained.
If not through sysfs, these parameters can be passed during runtime along with insmod as follows
insmod abc.ko <MODULE_PARAM_YOU_DEFINED>=value

MAKEFILE

To compile this as a module, the following simple makefile can be used. 

obj-m := abc.o
all:        make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:        make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

Points to be considered in the above Makefile : 
a) obj-m defines that the source will be compiled as a module. In Kernel Makefiles, we can find obj-CONFIG_<SOMETHING> This will define whether to build as module or as part of kernel image, based on the kernel configuration. 
b) all and clean are targets. When we say make clean, only the command beneath "clean:" will be executed. 
c) The above makefile builds based on a single source file. To compile multiple source files into one module, we can use as follows

abcdef-objs := abc.o def.o

d) This makefile shows building of modules for the build machine itself. If we are compiling for a different platform, cross compilation would come into picture. 

Building and Loading of Module

a) To build this, just entering make will do. In the build dir, we will get 

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

b) To load the module, insmod <module name> will work. If an error pops as "Operation not permitted", try with sudo. For more clarity on why this error occurs, refer to my previous post 

The messages printed will not come on console always. You might have to check it in dmesg. 

NOTE: If the kernel logs coming on the console are to be turned off, echo 0 > /proc/sys/kernel/printk

c) To unload a module, do a rmmod'

d) To do a modprobe, the module has to be added in /lib/modules/`uname -r`/modules.dep and the module should be available in /lib/modules/`uname -r`. So It is acceptable if upon doing modprobe ./abc.ko shows FATAL : Module not found. 

Hope this was helpful. 

Thanks,
Gomathi