In this page we are going to learn how to write a very basic Linux driver.
Required
Assumptions
Lets start
If you have not installed Kernel Source already, get the kernel-source-<kernel-version>
Or you can download kernel source from www.kernel.org
If you want to know about kernel compilation click here.
You need to prepare a makefile to compile the modules. Here is the standard Makefile.
#Makefile
KERNEL_DIR=linux-2.4.20
CFLAGS += -I/usr/src/${KERNEL_DIR}/include
CFLAGS += -DMODULE -D__KERNEL__
CFLAGS += -Wall
CFLAGS +=-I/usr/src/${KERNEL_DIR}/drivers/scsi
CFLAGS += -DMODVERSIONS -include /usr/src/${KERNEL_DIR}/include/linux/modversions.h -I.
#CFLAGS += -save-temps
all: module.o
module.o: mod1.o mod2.o
$(LD) -r $^ -o $@
mod1.o: mod1.c mod1.h
mod2.o: mod2.c mod2.h
clean:
rm -f module.o mod1.o mod2.o
This makefile builds the module module.o from the sub modules mod1.o and mod2.o.
You can change KERNEL_DIR variable according to your kernel version. For example if your kernel version is 2.4.20-2 then set KERNEL_DIR variable as
KERNEL_DIR=2.4.20-22
As everybody starts, we will also start with "Hello World". Our module will say Hello World from Kernel Space.
#Makefile
KERNEL_DIR=linux-2.4.20
CFLAGS += -I/usr/src/${KERNEL_DIR}/include
CFLAGS += -DMODULE -D__KERNEL__
CFLAGS += -Wall
all: hello.o
clean:
rm -f hello.o
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
int init_module(void)
{
printk("<1>Hello World\n");
return 0;
}
void cleanup_module()
{
printk("<1>Bye\n");
}
init_module is the entry point for the module, ie it will be called when the module is linked with kernel by default. init_module takes no arguement and returns int. If the return value is non-zero,it is taken as error and the module is not inserted/linked. Typically this function will do the detection/initialization of hardware, memory allocation etc.
cleanup_module is the exit point for the module, it will be called when the module is to be unloaded. It returns nothing and takes no arguement. Typically this function can do the tasks such as freeing the allocated memory, completing the I/O requests etc.
printk is similar to printf in user space. The only difference between printk and printf is printk does not support floating point format. <1> inside the arguement is the priority of the arguement. <0> is the highest priority and <7> is lowest priority. Depending upon the syslog configuration, the messages will be displayed on the console. You can get these messages from the file /var/log/messages also.
Download these two files ( hello.c and hello.mak ) and then run
$make -f hello.mak
to build hello.o
If compilation is not successful, please click here.
You must be a superuser to run the following command
$insmod ./hello.o
which installs (ie links the module into kernel) the hello.o module.
If the insmod is success, you should be able to see the message Hello World in the console. If you are not able to see the message, run 'dmesg' to see the driver messages. Even if you are not able to see this message in dmesg output, the module either is not inserted properly or the entry points are not right one. Check init_module method.
If insmod is failed, please click here.
hello.c can be written in more perfect way like this so this module can be statically linked with the kernel. We will see later about static linking of modules into kernel.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
int hello_init(void)
{
printk("<1>Hello World\n");
return 0;
}
void hello_exit()
{
printk("<1>Bye\n");
}
module_init(hello_init);
module_exit(hello_exit);
Use rmmod module-name (without .o) to remove the loaded module. In this case
$rmmod hello
will unload the hello module and Bye will be displayed on the console.
If you face problems in unloading the module, please click here.
Use lsmod to display the currently loaded modules. "Used by" column gives the list of processes using this driver.
This site has been visited
free hit counter
times
Last modified on: