The Linux Kernel/Modules

From Wikibooks, open books for an open world
Jump to: navigation, search

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:

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 a 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:

Is there supposed to be an example here?

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

Loaded modules are listed in /proc/modules. Use modinfo modulename.ko to determine module information. ? doesn't work use modinfo modulename

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

External references[edit]