Kernel Module Programming
Kernel Module Programming
Note: This picture is excerpted from Write a Linux Hardware Device Driver, Andrew OShauqhnessy, Unix world
Types of LKM
Device drivers Filesystem driver (one for ext2, MSDOS FAT16, 32, NFS) System calls Network Drivers TTY line disciplines. special terminal devices. Executable interpreters.
Loading a module - normally retricted to root - is managed by issuing the follwing command: # insmod module.o
rmmod
depmod kerneld
ksyms
Or % more /proc/modules
audio cmpci soundcore nfsd 37840 0 24544 0 4208 4 [audio cmpci] 70464 8 (autoclean)
SIMPLEST 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; } void cleanup_module(void) { printk(KERN_INFO "Goodbye world 1.\n"); }
EXPLAINING
module init is called when module is loaded module cleanup is called when module is unloaded
printk
The server cant use stdlib due to userspace/kernel space issues Most of C library is implemented in the kernel printk is printf for kernel programs.
Makefile
obj-m += hello-1.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
To remove
rmmod <modname> modprobe -r <modname>
hello-2.c
static int __init hello_2_init(void) { printk(KERN_INFO "Hello, world 2\n"); return 0; } static void __exit hello_2_exit(void) { printk(KERN_INFO "Goodbye, world 2\n"); } module_init(hello_2_init); module_exit(hello_2_exit);
What does it do
__init macro and __exit macro tells the kernel when we use this function This allows to free kernel memory that is used only at init
hello-3.c
static int hello3_data __initdata = 3; static int __init hello_3_init(void) { printk(KERN_INFO "Hello, world %d\n", hello3_data); return 0; } static void __exit hello_3_exit(void) { printk(KERN_INFO "Goodbye, world 3\n"); } //init exit
Hello-4.c
#define DRIVER_AUTHOR "Peter Jay Salzman <p@dirac.org>" #define DRIVER_DESC "A sample driver" static int __init init_hello_4(void) { printk(KERN_INFO "Hello, world 4\n"); return 0; } static void __exit cleanup_hello_4(void) { printk(KERN_INFO "Goodbye, world 4\n"); }
Hello-4.c (cont)
module_init(init_hello_4); module_exit(cleanup_hello_4); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("testdevice"); MODULE_AUTHOR(DRIVER_AUTHOR); /* Who wrote this module? */ MODULE_DESCRIPTION(DRIVER_DESC); /* What does this module do */
Additions in hello-4.c
We added licensing and information that removes the kernel is tainted message We also added some more info
Hello-5.c (simplified)
static int myint = 420; module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); MODULE_PARM_DESC(myint, "An integer"); static int __init hello_5_init(void) { int i; printk(KERN_INFO "Hello, world 5\n=============\n"); printk(KERN_INFO "myint is an integer: %d\n", myint); return 0; }
passing args
We demonstrate the effect of passing args The tutorial demonstrate how more args (from different types can be given)
Getting info
modinfo <modname> gives info on running modules we will get info for our modules 4 and 5.
Multiple files
We build a module using two files
start.c stop.c
start.c
#include <linux/kernel.h>/* We're doing kernel work */ #include <linux/module.h> /* Specifically, a module */ int init_module(void) { printk(KERN_INFO "Hello, world - this is the kernel speaking\n"); return 0; }
stop.c
#include <linux/kernel.h>/* We're doing kernel work */ #include <linux/module.h> /* Specifically, a module */ void cleanup_module() { printk(KERN_INFO "Short is the life of a kernel module\n"); }