Saturday, February 2, 2008

Linux loadable kernel moduels

Linux uses a monolithic architecture with file systems, device drivers, and other modules statically linked into the kernel image to be used at boot time. The use of dynamic kernel modules allows you to write portions of the kernel as separate objects that can be loaded and unloaded on a running system.

A kernel module is simply an object file containing routines and/or data to load into a running kernel. When loaded, the module code resides in the kernel's address space and executes entirely within the context of the kernel. Technically, a module can be any set of routines, with the one restriction that two functions, init_module() and cleanup_module(), must be provided. The first is executed once the module is loaded, and the second, before the module is unloaded from the kernel.The main functions to use to load /unload and inspect kernel modules are contained in the modutils package. They are:

/sbin/insmod (insert a module into the running kernel)

/sbin/rmmod (remove a module from the running kernel)

/sbin/lsmod (inspect modules in the running codes)

Note that to manage with kernel modules you have to be root. Use sudo command in ubuntu.

Once a module is loaded, it passes to form part of the operating system, hence it can use all the functions and access all variables and structures of the kernel. Similarly the global symbols created are made available or exported to other modules. If you don't want to share some symbol (variable or function), you have to declare it as static.

A module is built from a "C" source. Here is the simplest example of a kernel module, say hello.c

#include        /* Needed by all modules */
#include /* Needed for KERN_INFO */
#include /* Needed for the macros */

static int __init hello_start(void)
{
printk(KERN_INFO "Loading hello module...\n");
printk(KERN_INFO "Hello world\n");
return 0;
}

static void __exit hello_end(void)
{
printk(KERN_INFO "Goodbye Mr.\n");
}

module_init(hello_start);
module_exit(hello_end);

The compilation of the kernel module is different for Linux kernel 2.4 and 2.6. For checking Kernel versin
use the 'uname' command. The procedure given below is for 2.6 kernel.
Then we can create a makefile for compiling this with the following text.

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

Compile the hello.c file by using the command : make

Here , it may give error "Nothing to be done for all". The problem is you did not compile the Linux kernel till now.
So, compile the linux kernel by following the procedure given here:


http://embeddedbox.blogspot.com/2008/02/linux-26-kernel-compilation-for-ubuntu.html

After that make should generate hello.ko. This is the kernel module.
Now, we can insert the kernel module to Kernel using
insmode hello.ko


Check whether it is loaded properly with lsmod.

Note: Kernel offers a different version of printf() called printk().This works almost identically to the first except that it sends the output to a kernel ring buffer.
At any istant you can examine the contents of the buffer using the command dmesg.

You can get more information about linux kernel module programming from tldp.

No comments: