Saturday, July 19, 2008

Compiling and Inserting the First Kernel Module

Let’s now see how to compile the module program shown in previous post. We shall write a Makefile to make the procedure of compilation simpler. Below is a ‘template’ of a Makefile, which I use to compile my modules. The description follows.

########################################################################################

#Build as a loadable module
obj-m += ‘module_name_1’.o ‘module_name_2’.o
‘module_name_1’-objs := “space separated list of object files needed by ‘module_name_1’.o”
‘module_name_2’-objs := “space separated list of object files needed by ‘module_name_2’.o”

#Location of the current linux kernel source directory
SRC=/lib/modules/`uname -r`/build

#Working Directory
PWD=`pwd`

default:
make -C ${SRC} M=${PWD} modules

clean:
rm -f ${‘module_name’-objs}‘module_source_name.o ‘module_name’.ko ‘module_name’.mod.o
rm -f ‘module_name’.mod.c

################################################################################

obj-m tells the compiler which object files have to be created on make command. As many modules can be specified here, as we want to create. After that, for each module in obj-m list, a list of object files has to be specified which together link into that particular module’s object file.

Under /lib/modules, there is one subdirectory for each kernel installed in your system, with the name of that particular kernel. Each of these directories contain source (code, module object files) of the corresponding kernel image. The shell command uname -r gives as output the name of the currently running kernel. Therefore, SRC environment variable stores the path to the skeleton of source code of currently running kernel.

This path is specified to let make read the kernel top level Makefile, which defines the rules to make the target, i.e. modules. This environmental variable can alternatively/additionally be passed at command line, as an argument to make. As is the case with Makefiles, SRC specified at command line will take precedence over the one specified in Makefile.
The -C switch in make changes the current directory to $SRC (kernel source directory) to find kernel top level Makefile. M=dir specifies the directory where the module to be built is present. M=dir modules instructs to make all those modules in the directory dir, listed in variable obj-m.

The myFirstModule Makefile:


#####################################################################################

#Build as a loadable module
obj-m += myFirstModule.o
myFirstModule-objs:= myFirstModuleSource.o

#Location of the linux source directory
SRC=/lib/modules/`uname -r`/build

#Working Directory
PWD=`pwd`

default:
make -C ${SRC} M=${PWD} modules

clean:
rm -f ${ myFirstModule-objs} myFirstModule.o myFirstModule.ko myFirstModule.mod.o
rm -f myFirstModule.mod.c

###############################################################################


Running make:
[shweta@localhost modules]# make
make -C /lib/modules/`uname -r`/build M=`pwd` modules
make[1]: Entering directory `/usr/src/kernels/2.6.9-42.EL-smp-i686'
CC [M] /home/Shweta/wikalk/modules/myFirstModuleSource.o
LD [M] /home/Shweta/wikalk/modules/myFirstModule.o
Building modules, stage 2.
MODPOST
CC /home/Shweta/wikalk/modules/myFirstModule.mod.o
LD [M] /home/Shweta/wikalk/modules/myFirstModule.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.9-42.EL-smp-i686'


Inserting (or linking) the module:
The shell provides two commands to insert a module into the kernel, insmod and modprobe, which both do the same set of activities. The difference lies in how they search for the module binary to load.

insmod requires the absolute path of the module as argument:
[shweta@localhost modules]# insmod /root/wikalk/modules/myFirstModule.ko
modprobe requires just the module name as argument:

[shweta@localhost modules]#modprobe myFirstModule
The modprobe searches for the module name in the default path /lib/modules/`uname -r`. If no module with the given name is found, an error is displayed.

So now, our myFirstModule is inserted/removed as follows:
[shweta@localhost modules]#insmod myFirstModule.ko
Hey! myFirstModule is in the kernel now.

[shweta@localhost modules]#rmmod myFirstModule
myFirstModule is removed from kernel
myFirstModule was in kernel for 143 seconds.

Some Points to Remember:

  • After inserting a module, it needs to be explicitly unloaded or else it will be removed when the system is shut down. However, it is a better way to explicitly unload the module if it no more required otherwise it will consume system resources (memory, CPU...) for no use.
  • If the return statement is missing in init() function, the compilation succeeds without any errors or warnings. But insmod gives “error inserting myFirstModule.ko

No comments: