8.2. Module UtilitiesWe had a brief introduction to module utilities in Listing 8-5. There we used the module utility modprobe to insert and remove a device driver module from a Linux kernel. A number of small utilities are used to manage device driver modules. This section introduces them. You are encouraged to refer to the man page for each utility, for complete details. In fact, those interested in a greater knowledge of Linux loadable modules should consult the source code for these utilities. Section 8.6.1, "Suggestions for Additional Reading" at the end of this chapter contains a reference for where they can be found. 8.2.1. insmodThe insmod utility is the simplest way to insert a module into a running kernel. You supply a complete pathname, and insmod does the work. For example: $ insmod /lib/modules/2.6.14/kernel/drivers/char/examples/hello1.ko This loads the module hello1.ko into the kernel. The output would be the same as shown in Listing 8-5namely, the Hello message. The insmod utility is a simple program that does not require or accept any options. It requires a full pathname because it has no logic for searching for the module. Most often, you will use modprobe, described shortly, because it has many more features and capabilities. 8.2.2. Module ParametersMany device driver modules can accept parameters to modify their behavior. Examples include enabling debug mode, setting verbose reporting, or specifying module-specific options. The insmod utility accepts parameters (also called options in some contexts) by specifying them after the module name. Listing 8-6 shows our modified hello1.c example, adding a single module parameter to enable debug mode. Listing 8-6. Example Driver with Parameter
Three lines have been added to our example device driver module. The first declares a static integer to hold our debug flag. The second line is a macro defined in .../include/linux/moduleparam.h that registers the module parameter with the kernel module subsystem. The third new line is a macro that registers a string description associated with the parameter with the kernel module subsystem. The purpose of this will become clear when we examine the modinfo command later in this chapter. If we now use insmod to insert our example module, and add the debug_enable option, we should see the resulting output, based on our modified hello1.c module in Listing 8-6. $ insmod /lib/modules/.../examples/hello1.ko debug_enable=1 Hello Example Init - debug mode is enabled Or, if we omit the optional module parameter: $ insmod /lib/modules/.../examples/hello1.ko Hello Example Init - debug mode is disabled 8.2.3. lsmodThe lsmod utility is also quite trivial. It simply displays a formatted list of the modules that are inserted into the kernel. Recent versions take no parameters and simply format the output of /proc/modules.[5] Listing 8-7 is an example of the output from lsmod.
Listing 8-7. lsmod Example Output Format
Notice the rightmost column labeled Used by. This column indicates that the device driver module is in use and shows the dependency chain. In this example, the jbd module (journaling routines for journaling file systems) is being used by the ext3 module, the default journaling file system for many popular Linux desktop distributions. This means that the ext3 device driver depends on the presence of jbd. 8.2.4. modprobeThis is where the cleverness of modprobe comes into play. In Listing 8-7, we see the relationship between the ext3 and jbd modules. The ext3 module depends on the jbd module. The modprobe utility can discover this relationship and load the dependent modules in the proper order. The following command loads both the jbd.ko and ext3.ko driver modules: $ modprobe ext3 The modprobe utility has several command line options that control its behavior. As we saw earlier, modprobe can be used to remove modules, including the modules upon which a given module depends. Here is an example of module removal that removes both jbd.ko and ext3.ko: $ modprobe -r ext3 The modprobe utility is driven by a configuration file called modprobe.conf. This enables a system developer to associate devices with device drivers. For a simple embedded system, modprobe.conf might be empty or might contain very few lines. The modprobe utility is compiled with a set of default rules that establish the defaults in the absence of a valid modprobe.conf. Invoking modprobe with only the -c option displays the set of default rules used by modprobe. Listing 8-8 represents a typical modprobe.conf, which might be found on a system containing two Ethernet interfaces; one is a wireless adapter based on the Prism2 chipset, and the other is a typical PCI Ethernet card. This system also contains a sound subsystem based on an integrated Intel sound chipset. Listing 8-8. Typical modprobe.conf File
When the kernel boots and discovers the wireless chipset, this configuration file instructs modprobe to load the orinoco_pci device driver, bound to kernel device eth1, and pass the optional module parameter orinoco_debug=9 to the device driver. The same action is taken upon discovery of the sound card hardware. Notice the optional parameters associated with the sound driver snd-intel8x0. 8.2.5. depmodHow does modprobe know about the dependencies of a given module? The depmod utility plays a key role in this process. When modprobe is executed, it searches for a file called modules.dep in the same location where the modules are installed. The depmod utility creates this module-dependency file. This file contains a list of all the modules that the kernel build system is configured for, along with dependency information for each. It is a simple file format: Each device driver module occupies one line in the file. If the module has dependencies, they are listed in order following the module name. For example, from Listing 8-7, we saw that the ext3 module had a dependency on the jbd module. The dependency line in modules.dep would look like this: ext3.ko: jbd.ko In actual practice, each module name is preceded by its absolute path in the file system, to avoid ambiguity. We have omitted the path information for readability. A more complicated dependency chain, such as sound drivers, might look like this: snd-intel8x0.ko: snd-ac97-codec.ko snd-pcm.ko snd-timer.ko \ snd.ko soundcore.ko snd-page-alloc.ko Again, we have removed the leading path components for readability. Each module filename in the modules.dep file is an absolute filename, with complete path information, and exists on a single line. The previous example has been truncated to two lines, to fit in the space on this page. Normally, depmod is run automatically during a kernel build. However, in a cross-development environment, you must have a cross-version of depmod that knows how to read the modules that are compiled in the native format of your target architecture. Alternatively, most embedded distributions have a method and init script entries to run depmod on each boot, to guarantee that the module dependencies are kept up-to-date. 8.2.6. rmmodThis utility is also quite trivial. It simply removes a module from a running kernel. Pass it the module name as a parameter. There is no need to include a pathname or file extension. For example: $ rmmod hello1 Hello Example Exit The only interesting point to understand here is that when you use rmmod, it executes the module's *_exit() function, as shown in the previous example, from our hello1.c example of Listings 8-1 and 8-6. It should be noted that, unlike modprobe, rmmod does not remove dependent modules. Use modprobe -r for this. 8.2.7. modinfoYou might have noticed the last three lines of the skeletal driver in Listing 8-1, and later in Listing 8-6. These macros are there to place tags in the binary module to facilitate their administration and management. Listing 8-9 is the result of modinfo executed on our hello1.ko module. Listing 8-9. modinfo Output
The first field is obvious: It is the full filename of the device driver module. For readability in this listing, we have truncated the path again. The next lines are a direct result of the descriptive macros found at the end of Listing 8-6namely, the filename, author, and license information. These are simply tags for use by the module utilities and do not affect the behavior of the device driver itself. You can learn more about modinfo from its man page and the modinfo source itself. One very useful feature of modinfo is to learn what parameters the module supports. From Listing 8-9, you can see that this module supports just one parameter. This was the one we added in Listing 8-6, debug_enable. The listing gives the name, type (in this case, an int), and descriptive text field we entered with the MODULE_PARM_DESC() macro. This can be very handy, especially for modules in which you might not have easy access to the source code. |