Managing moduls on the Linux kernel November 15, 2010Posted by Tournas Dimitrios in Linux, Linux course.
While Linux is officially a monolithic kernel, it does permit dynamic extensibility with loadable kernel modules. In this article, we’ll explore the various tools and processes that support dynamic kernel customization. We’ll also explore the various configuration mechanisms available for module configuration.
Linux is a monolithic kernel, which means that the kernel runs in the supervisory mode of the processor. The kernel implements the basic interfaces to the hardware and presents APIs to user-space (and kernel) applications that require access to it. This is in contrast to micro-kernel architecture, which implements only basic services in the kernel, and pushes higher-level services outside of the kernel core. One of the primary advantages to micro-kernels is that they are eminently extensible. Since most services are implemented outside of the kernel proper, it’s easy to start and stop services based upon their need.
Fortunately, while Linux is a monolithic kernel, it does provide the means for dynamic extension through the use of kernel modules. Kernel modules are special objects that can be inserted into the kernel, as well as removed, dynamically. Upon insertion, they extend services to the kernel as well as use services (through a process known as dynamic binding).
Linux kernel modules are also special in that they present two interfaces present only in modules. These required interfaces provide for initialization (when the module is first inserted) and for cleanup (when the module is removed).
You’ll find kernel modules used in variety of ways that demonstrate how integral they are to Linux. For example, you’ll find loadable modules used for networking and filesystem drivers, as well as drivers for various hardware supported by Linux. This is valuable because in a standard distribution, if the hardware is not present, the module is not loaded and therefore no space is taken by the module.
Consider a monolithic kernel without loadable modules. A kernel would need to be built for each configuration, or a kernel with all options included would be needed which would result in a massive kernel.
The detailed methods behind module management in the kernel and dynamic binding are well-covered elsewhere, so more details can be found through the available resources at the end of this article. Let’s now explore the tools that are available for module management to understand what they are.
Linux provides a useful set of module commands that range from reviewing the current set of modules inserted into the kernel, to commands that insert and remove modules from the kernel. We’ll explore the available commands in this section.
Figure 1 shows the four major commands used for module management along with their relationships to some of the important module system files. We’ll explore these relationships as we discuss the commands.
Figure 1 Major Module Commands and their Relevant Files.
Thelsmod> (or list modules) command can be used to list the modules that are currently installed into the kernel. The result is a list of modules by name that includes the memory size of the module, the use count (how many other modules use this module) and an optional list of modules sorted by name that this modules relies on. An example output of lsmod is shown here:
$ lsmod Module Size Used by af_packet 23812 2 rfcomm 41744 2 l2cap 25728 13 rfcomm bluetooth 61156 4 rfcomm, l2cap ...
With the information provided by lsmod, one could easily generate a graph showing the kernel modules and their full dependencies.
The insmod (or insert module) command can be used to insert a module into the kernel. For the 2.6 kernel, this must be a kernel object (suffixed with .ko). If symbols exist within the module, they can be initialized at install time through the insmod command. The following example illustrates installing a module with an initialization option.
$ insmod my_module.ko my_option=1
An error message would be generated on the command-line if there was an error during install. Otherwise, the user can review the install and any output from the module using the dmesg command.
But using this command isn’t actually recommended. Later we’ll explore the modprobe command, which is the best and most efficient way to install modules into the kernel.
The rmmod> (or remove module) command can be used to remove a module from the kernel. The module name (excluding the .ko) is specified to identify the module to remove. The kernel will not remove a module that is currently being used in the kernel (a non-zero use count), but a -w option can be specified to rmmod to instruct the kernel to remove it once the use-count has decreased to zero. The following example illustrates removing a module with rmmod.
$ rmmod my_module
Like the insmod command, it’s recommended to use the modprobe command instead to remove modules.
The depmod command is used to map interdependencies between modules. For example, if a module is to be loaded that is dependent upon another module, then that module should be loaded first. But how is this information determined? The answer is the depmod command.
The depmod command is executed with a module named as an argument, and the result is a list of dependencies of that module (which could involve dependencies of those particular modules) stored in a file called modules.dep. This file contains a list of modules and each of the modules upon which it’s dependent. Use of the depmod is as simple as shown below.
$ depmod my-module.ko
To see whatdepmod would do without taking any action on modules.dep, the
–n option can be used. This emits the changes that would be made to modules.dep to standard out instead.
This module dependency process is also done recursively, so that if a required module has other module dependencies, these are identified and stored as well. This data is ultimately used by modprobe>, discussed next.
The modprobe command is the most important command for module management. It’s actually a wrapper built over the basic insmod and rmmod command but it implements much more intelligent behavior. Recall that insmod simply attempts to load a module, but if that module is dependent upon others, the module will exit due to missing symbols. The modprobe command uses previously identified module dependency information to make the install and removal process seamless.
When the modprobe command is executed for a module to be installed, modprobe will first ensure that all necessary modules are installed (as defined within module.dep). If not, the modules are installed first. This process is recursive such that if a module is to be installed that has other module dependencies, those module dependencies are also considered. This makes installing modules less of a process of trial and error, and more of a painless and error-free task. Installing a module with modprobe is demonstrated below. This could also be performed with the –v flag which tells modprobe to be verbose about its actions.
$ modprobe my-module.ko
The modprobe command can also be used for intelligently removing modules. Rather than blindly attempting to remove a module, as would be the case with rmmod, modprobe intelligently figures out what modules must be removed in order to remove the module in question. Further, it identifies whether those modules can be removed (are they actively used, for example). To use modprobe for module removal, the –r option is used:
$ modprobe –r my-module.ko
Numerous other options exist for modprobe, such as listing modules matching a wildcard (with the –l option), redirecting error output to syslog rather than standard out (-s) and dry-running the process without installing or removing modules (-n).
Proc Filesystem Files for Modules
The proc filesystem (a virtual filesystem that is constructed dynamically) provides files that are focused on Linux modules. These are defined below with their link to the module subsystem.
The file /proc/modules provide a list of the modules that are currently installed into the kernel. In fact, the information found here is a superset of that provided by the lsmod command. The following example shows a short snippet of the /proc/modules output:
$ cat /proc/modules af_packet 23812 2 - Live 0xe8b8d000 rfcomm 41744 2 - Live 0xe0b9b000 l2cap 25728 13 rfcomm, Live 0xe0b72000 bluetooth 61156 4 rfcomm, l2cap, Live 0xe0b7d000
While similar to the output of lsmod, this presents a bit more detail. The output begins with the module name and its size, followed by the number of users of the module. The next item, Live, indicates that the module state is live. It could also be Loading, or Unloading, indicating that the module is in the midst of the insmod or rmmod process. Finally, the last value indicates the memory offset in the kernel where this module begins. This can be useful for kernel debugging.
The file /proc/kallsyms contains the symbol table of the kernel (what was previously called /proc/ksyms prior to the 2.6 kernel). This file contains all symbols that are exported by the kernel, which is useful for dynamically linking (resolving kernel symbols in a module entering the kernel).
Modules are one of the most important innovations in the Linux kernel. While they've been there for a while, they've enabled Linux to be dynamically configurable. They've also permitted the production of small kernels with dynamic modules used for optional devices, file-systems, or other hardware.
Modules are also just as time efficient as statically compiling into the kernel. Therefore, modules are not available and convenient, but recommended to produce small focused kernels that can automatically and dynamically scale to the hardware environment.
To learn more about the internal details of loadable modules within the 2.6 kernel, check out “Anatomy of Linux loadable kernel modules.” In this article you’ll find kernel module anatomy, module life-cycles, and the internal kernel process for module loading and unloading.
The Linux Kernel Module Programming Guide provides a good introduction to kernel module programming. It covers basic module programming and the proc file-system. This guide is a work-in-process, but has been updated for the 2.6 kernel. The Linux Documentation Project also provides a nice concise summary of kernel modules.
About the Author: M. Tim Jones is a senior architect and the author of Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming (now in its second edition), AI Application Programming (in its second edition), and BSD Sockets Programming from a Multilanguage Perspective. His engineering background ranges from the development of firmware for geosynchronous spacecraft to embedded systems architecture and networking protocols development. Tim is a Senior Architect for Emulex Corp. in Longmont, Colorado.