The Linux Kernel/Modules

A kernel module is a code that can be loaded into the kernel image at will, without requiring users to rebuild the kernel or reboot their computer. Modular design ensures that you do not have to make a monolithic kernel that contains all code necessary for hardware and situations.

Common kernel modules are device drivers, which directly access computer and peripheral hardware.

Kernel modules have a .ko extension as of kernel 3.0.

Using modules

edit

To determine loaded modules run the command lsmod, which reads the file /proc/modules. An example output of lsmod is the following:

Module                  Size  Used by
ctr                    13049  1 
ccm                    17773  1 
snd_hda_codec_hdmi     46368  1 
snd_hda_codec_cirrus    18855  1 
btusb                  32412  0 
hid_generic            12548  0 
arc4                   12608  2 
b43                   387371  0 
mac80211              630669  1 b43
hid_apple              13386  0 
bcm5974                17589  0 
joydev                 17381  0 
cfg80211              484040  2 b43,mac80211
ssb                    62379  1 b43
hid_holtek_mouse       12625  0 

Please note that the output printed by lsmod is usually very long and contains several kernel modules listed. This example has been shortened for obvious reasons.

In order to add a module to the kernel you can use the modprobe command. A kernel module daemon kmod, often executes modprobe in order to load a module. Modprobe is passed a string argument that may be an actual module name or an alias to module. Modprode search /proc/modprobe.conf to relate an module alias to an actual module. In order to determine module dependencies, modprobe searches /lib/module/version/modules.dep and determines if other modules must be loaded before the requested module can be. The modules.dep file is created using the depmod -a command, which determines if a particular module calls functions or variables (symbols) that are defined by other modules.

If there are dependencies, insmod loads these before it loads the requested module. While insmod requires detailed instructions about the path and file names of requested modules, modprobe does not. Here is an example for "spidev.ko":

sudo modprobe spidev

Modprobe, insmod and depmod are found in the module-init-tools or kmod packages.

Loaded modules are listed in /proc/modules. Use modinfo modulename, for file modulename.ko, to determine module information. Here is an example:

modinfo spidev

Note that you cannot use X, such as an xterm, as the kernel only prints directory to consoles or log files.

Writing and debugging modules

edit

A simple module

edit

The simplest kernel module:

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
    printk(KERN_ALERT "Hello, world\n");
    return 0;
}
static void hello_exit(void)
{
    printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);

Kernel modules must always contain these two functions, init_module and cleanup_module. Insmod calls init_module when it loads the modules into the kernel and rmsmod calls cleanup_module when it removes the module. printk() is a logging macro used by the kernel and is assigned a priority of <1>. Kernel priorities, of which there are eight, are defined in kernel.h. Each kernel priority has a particular intended meaning and a related definition:

43 #define KERN_EMERG      "<0>"   /* system is unusable                   */
44 #define KERN_ALERT      "<1>"   /* action must be taken immediately     */
45 #define KERN_CRIT       "<2>"   /* critical conditions                  */
46 #define KERN_ERR        "<3>"   /* error conditions                     */
47 #define KERN_WARNING    "<4>"   /* warning conditions                   */
48 #define KERN_NOTICE     "<5>"   /* normal but significant condition     */
49 #define KERN_INFO       "<6>"   /* informational                        */
50 #define KERN_DEBUG      "<7>"   /* debug-level messages                 */

When using printk() when syslogd and klogd are running, the output of printk() will be appended to /var/log/messages. printk() if called with low priority will only be appended to /var/log/messages. To ensure that it prints to the console use KERN_ALERT priority.

Compiling the simple module

edit

Kernel modules are not compiled in the same manner as userspace code. Here is a sample makefile:

obj-m += hello.o

all: modules

.DEFAULT:
	$(MAKE) -C $(KDIR) M=$$PWD $@

Evoke the command make to compile your simple module.

Using the module_init() and module_exit() macros you can change the name of the init_module() and cleanup_module(void).

The __init macro frees the memory of initialization function in the module after the built-in driver, for example, has been loaded. This does not occur, however, with modprobe.

The __exit macro prevents the cleanup_module from being loaded during initialization, as it will not be needed in the kernel while the kernel is in use. These macros can be found in linux/init.h, and are useful for managing memory. __initdata is analogous to __init but for variables.

The MODULE_LICENSE() macro allows you to determine the license of code, and define it for your module.

MODULE_PARM() allows you to pass command line parameters when insmod initializes the module.

In order to span modules across several files, the make file must be altered.

obj-m += hello.o
obj-m += startstop.o
startstop-objs := start.o stop.o

default: modules

.DEFAULT:
	$(MAKE) -C $(KDIR) M=$$PWD $@

Testing your simple module

edit
% make
make[1]: Entering directory `/usr/src/linux-2.6.10'
CC [M] /home/ldd3/src/misc-modules/hello.o
Building modules, stage 2.
MODPOST
CC /home/ldd3/src/misc-modules/hello.mod.o
LD [M] /home/ldd3/src/misc-modules/hello.ko
make[1]: Leaving directory `/usr/src/linux-2.6.10'
% su
root# insmod ./hello.ko
Hello, world
root# rmmod hello
Goodbye cruel world
root#

Writing modules

edit

The symbols that are available to modules can be found in /proc/kallsyms.

Modules can be written to replace the kernel's system calls.

To see what system calls are executed by a userspace process evoke the process using strace.

Kernel space and userspace

edit

A CPU has different modes, 80386 has four. For a description of rings, see the Wikipedia rings entry.

References

The Linux Kernel Module Programming Guide
http://lwn.net/images/pdf/LDD3/ch02.pdf