Copied from the Kernel Module Programming Guide (KMPG)
/* hello-1.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
return 0; /* 0 means success in the kernel */
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
Note that printk takes a level before its format - the level is actually a string that gets pasted together with the format, so there is no comma between the two. Printk supports most printf format codes, although you don't want to use floating point.
# Makefile obj-m += hello-1.o KERNEL_DIR := /lib/modules/$(shell uname -r)/build all: make -C $(KERNEL_DIR) M=$(PWD) modules clean: make -C $(KERNEL_DIR) M=$(PWD) clean
If you've built modules for the 2.4 kernel (or earlier) the 2.6 build system is very simple in comparison - you just point 'make' at the kernel source directory, pass M=$(PWD), and it just works. If your kernel source tree is somewhere else, then you can specify it in the makefile or on the command line:
make KERNEL_DIR=/some/path/linux-1.67.2 all
Here are the results of compiling and installing this module:
[pjd@george tmp]$ make all make -C /lib/modules/2.6.17-1.2174_FC5/build M=/tmp modules make[1]: Entering directory `/usr/src/kernels/2.6.17-1.2174_FC5-i586' CC [M] /tmp/hello-1.o Building modules, stage 2. MODPOST CC /tmp/hello-1.mod.o LD [M] /tmp/hello-1.ko make[1]: Leaving directory `/usr/src/kernels/2.6.17-1.2174_FC5-i586' [pjd@george tmp]$ sudo insmod hello-1.ko [pjd@george tmp]$ sudo rmmod hello-1 [pjd@george tmp]$ dmesg | tail ... hello_1: module license 'unspecified' taints kernel. Hello world 1. Goodbye world 1.
To remove the 'taint' message you need to specify a GPL license, by adding the following line at the bottom of the .c file:
MODULE_LICENSE("GPL");
Some operating systems (e.g. Windows 2000, XP) export a kernel-level interface (e.g. for drivers) which remains stable for years, across many systems; that's why the driver disk that came with an old network card may still work. The kernel-level interface in Linux not only changes frequently between versions, but can even change depending on configuration options. (the biggest change here is probably due to enabling or disabling SMP)
To prevent errors due to a mismatch in interfaces (e.g. different numbers of function arguments) Linux provides the module versioning feature. [TODO - write more] You should never have trouble with symbol versions if you are compiling against the same kernel tree that you are running kernels from.
Of course, we haven't talked about the code inside the module yet...