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
editTo 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
editA simple module
editThe 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
editKernel 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
editThe 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
editA CPU has different modes, 80386 has four. For a description of rings, see the Wikipedia rings entry.
References