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
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.

A simple module
The simplest kernel module:

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:

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
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
% 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
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
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