The kernel is the core of any operating system and is responsible for managing system resources. Broadly, the Linux kernel can be of two types.
Monolithic kernels: This is a single executable file in which all the modules are part of the kernel. In order to add anything to the existing kernel, developers have to rebuild the complete kernel and add the new functions.
Modular kernels: Modular kernels provide developers an option to add new functionality to the existing kernel by plugging the new code, also known as ‘modules’ at run time.
In this article, let’s explore how to write a simple pluggable kernel module for the Linux kernel.
What are kernel modules?
Kernel modules are pieces of code, which can be loaded and unloaded from a kernel, on demand. A Linux Kernel Module (LKM) can be added at run time without even requiring a reboot or even a rebuild of the running kernel. The LKM will have a .ko extension.
The LKM will act as the interface between a user space application and the Linux kernel. Any request to access the hardware from an application goes via the LKM to the kernel, and then to the actual hardware (see Figure 1).
To know the list of modules running in a Linux kernel you can use the ‘lsmod’ command, which actually gives the list of running modules at that point of time, by reading ‘/proc/modules’ as shown in Figure 2.
Kernel modules can be broadly categorised as character, block or network modules.
Kernel module management commands
insmod <module-name>: This command is to insert the new module into the kernel
lsmod: This lists the modules that are currently loaded in the kernel
modinfo <module-name>: This is to get complete information about the module
rmmod <module-name>: This command is to remove the module from the kernel
modprobe <module-name>: This works the same as insmod but it uses ‘Module Stacking’ to load any module that is required to load the current module.
modprobe r <module>: To remove the module from the kernel
dmesg: Shows the contents of the kernel ring buffer
For an example of how to use module management commands, please refer to Figure 3.
Now let’s understand the concepts we used to write the above module.
hello_init(): This is called when the module is inserted into the kernel using insmod. This function gets invoked by the ‘module_init’ macro. The init function is responsible for registering the module with the kernel.
hello_exit(): This function is called when the module is removed from the kernel using rmmod. This function gets invoked by the ‘module_exit’ macro. This function removes and cleans up the inserted module.
Macros module_init (hello_init) & Module_init (hello_exit): Using these macros, programmers can give user defined names to the init and cleanup functions. These macros are defined in <linux/init.h>.
Printk: In kernel module programming, ‘printk’ is used to print kernel messages in to the kernel logs. Printk messages are linked to the priority associated with them. For all behavioural purposes, we use ‘printk’ in kernel module programming much as we use ‘printf’ in user level C programs.
Compiling and building the module
Use a makefile to compile and build the sample helloworld module. Refer the Figure 5, where the makefile for this module is written.
Use the ‘make’ command to compile and build the helloworld kernel module program. The ‘make’ command console output screenshot is shown in Figure 6.
Once the module is compiled and built using make, the ‘module.ko (helloworld.ko)’ will be created.
Insert and remove the sample helloworld kernel module
Now that we have the helloworld.ko file, insert this module into or remove it from the kernel by using the insmod/rmmod commands. Please refer the Figure 7 for this.
Passing run time arguments to the module
As with any other program, run time arguments can be passed to the kernel module also, as follows:
module_param (str, int, S_IRUGO) macro is used str name of the variable int type of the variable S_IRUGO permission flag
Figure 8 shows the sample output of passing runtime arguments for the helloworld kernel module.
The Linux Kernel Module Programming Guide: http://www.tldp.org/LDP/lkmpg/2.6/lkmpg.pdf