Using loadable kernel modules (called modules for short), today’s Linux kernels support a wide variety of peripheral devices. Modules are kernel components that are designed to do a specific job, such as supporting a specific brand and model of adapter card. These stand-alone modular components can be added to, or removed from, the running kernel without any harm being done to the kernel’s functionality. Whether or not you’ve studied modules, you should know that you’re already using them. When you installed your Linux distribution, the installation utility scanned your system for hardware and then selected, configured, and installed the appropriate modules. The whole process should have been automatic and relatively painless.
The shock comes later—when you realize that some of your peripherals, such as sound, aren’t working. Some distributions, including Red Hat, come with sound configuration utilities that can deal with sound cards. Inevitably, however, you’ll run into difficulties when you try to get some piece of hardware to work. For example, an adapter may be present in your system when you install Linux, but the installation utility will ignore the adapter. Many Linux users find that the installation utility fails to detect and install the Iomega Zip Zoom SCSI adapter. Whatever the problem, you’re in for a challenge.
In this Daily Drill Down, I’ll help you pick your way through the module maze. A good conceptual grounding goes a long way, especially when you’re dealing with a topic that goes straight to the heart of Linux’s daunting complexity. I’ll explain why modules are added to the Linux kernel design, what they do, where they’re found on your system, and which commands manipulate them. Then, I’ll offer a generic approach to module configuration, and I’ll explain how you can get the configuration information that you need for specific module-installation problems.
Introducing loadable kernel modules
Linux pioneers were hardy folk. Back in the early days of the Linux kernel, support for peripherals had to be compiled into the kernel, which was the heart of the Linux operating system. Unfortunately, that meant that they had to recompile the kernel every time they installed a new peripheral. Although recompiling the kernel isn’t as difficult as it sounds, it’s still a very time-consuming process, and it’s prone to error. If you make a mistake, your system won’t run, and you could face hours of troubleshooting before you’re back in business.
Fortunately, there’s a better way. Starting with version 2 of the Linux kernel, the code that supports adapter cards and filesystems was moved out of the kernel into loadable kernel modules. Modules are helpful for two reasons:
- Convenience: With modules, you don’t have to recompile the kernel every time you change an adapter or install a new one. Modules can be loaded into (or unloaded from) the kernel without any recompilation being necessary.
- Efficiency: Since modules move so much code out of the kernel, the kernel’s authors can keep the kernel lean and mean. That’s one of the reasons why Linux performs so well. Of course, the kernel grows in size when you load the modules, but modules can be loaded dynamically when they’re needed and unloaded when they’re not in use. That’s exactly what kerneld, one of those mysterious daemons on your system, does. Daemons are programs that run in the background but spring into action as needed. This particular daemon loads modules when they’re needed and removes them if they haven’t been used for a specified period (usually one minute by default).
If you’re ever told to recompile the kernel, then you’ll know that the Linux documentation that you’re reading is out of date. Of course, recompiling the kernel is still necessary under certain circumstances, but such situations are rare—unless you’re upgrading to a new version of the kernel. Unfortunately, many of the Linux HOWTOs haven’t been updated sufficiently since the move to the modular architecture was made.
What do modules support?
In general, modules are used to support specific brands and models of hardware components, such as 3COM 3c575 Ethernet adapters or Crystal CS4232 sound chips. Here’s an overview of the types of components that modules support:
- Block devices (such as floppy drives, tape drives, and RAID drives)
- CD-ROM drives (including CR-R and CD-RW recorders)
- Ethernet adapters and other network devices (including ISDN adapters)
- Input devices (such as mice, joysticks, and graphics tablets)
- PC or PCMCIA cards (including network adapters and modems)
- SCSI adapters and devices that are installed on the SCSI bus
- Sound cards (including MIDI synthesizers)
Modules aren’t designed just for peripherals. For example, the current Linux kernel uses modules to provide support for filesystems and certain networking capabilities, such as IP masquerading. Thus, it’s inaccurate to refer to modules as device drivers (programs that support specific peripheral devices).
Where are modules stored?
Since modules are so closely linked to kernel functionality, Linux distributions are reasonably consistent in the way in which they’re stored and organized. Current kernel standards call for compiled modules to be stored in a directory called /lib/modules/kernel-version (where kernel-version corresponds to the version number of the Linux kernel that you’re currently running, such as 2.2.12-20).
Within this directory, you’ll see a number of subdirectories that correspond to the different types of modules (such as block, cdrom, net, pcmcia, and scsi). Within each directory, you’ll see compiled modules that have the .o extension (o is short for object file). The first part of the filename is the module’s name; thus, aha152x is the name of the module stored in aha152x.o. You’ll need to know the module name so that you can refer to the module in certain commands.
What if this directory doesn’t exist? That’s not likely because your system wouldn’t be able to do much of anything without module support. It’s easy to fix the problem, however. Just switch to /usr/src/linux, type make modules, and press [Enter]. When this program finishes, type make modules_install and press [Enter]. To create a module dependency table, type depmod -a and press [Enter].
If you upgrade to a new kernel version, don’t forget to upgrade the modules, too. Use the above steps to compile the new module versions that are designed to work the kernel that you’ve installed.
Loading modules: An overview
It’s very nice to have lots of modules sitting in /lib/modules, but they don’t do anything except take up disk space. To get them working, you need to load them into the kernel. You can use various commands to accomplish this feat. The following utilities will help you load a module into the kernel:
- insmod is the earliest and simplest module-loading utility. Part of the modutils package, insmod loads a module into the kernel, where it remains until you remove it (with rmmod) or shut down your system. To load modules automatically at the start of each session, add the appropriate insmod command to your system’s init script (such as /etc/rc.d/rc.sysinit).
- lsmod is a simple utility that displays the modules that are currently running. It’s not very fancy. In fact, you can get pretty much the same information by typing cat /proc/modules and pressing [Enter]. (The /proc/modules directory contains a list of the modules that are currently installed in the kernel.)
- modprobe and depmod are more recent and more complex utilities than insmod. For instance, modprobe is a wrapper for insmod that provides additional functionality in three ways. First, modprobe includes an option that runs all of the modules in a directory (or all of the modules with names that match a pattern you’ve specified) until it finds one that works. Second, modprobe can install or remove modules based on the information in a configuration file (called /etc/conf.modules or /etc/modules.conf). Third, modprobe uses depmod, a utility that scans all the compiled modules and determines which modules depend on other modules for their functionality. For example, the Sound Blaster module requires basic sound support (sound.o). If you run depmod with the -a option after you install a new kernel, the utility constructs the dependency table (called modules.dep). Before loading a module, modprobe consults this table. If the module that you’re trying to load requires another module to be loaded, modprobe takes care of this task automatically.
- kerneld is a daemon (a memory-resident program) that notices when a program requests a feature that isn’t available in the kernel. The daemon will run modprobe, which loads the required module. That’s nice, but what’s especially great about kerneld is its ability to remove unused modules from the kernel after a specified period of inactivity (usually one minute). With this feature enabled, your kernel runs as effectively as possible, and it takes on the extra burden of module code only when the code is required. Most Linux distributions install kerneld by default; it’s probably running on your system already.
Probing for modules
As its name suggests, modprobe probes a hardware device to see which module will work with it. However, the process isn’t very sophisticated. Basically, modprobe keeps trying modules, one after the next, until it finds one that works. To use modprobe in this way, type modprobe -t and then the name of the directory that contains the modules that you want to try (such as /lib/modules/kernel-version/pcmcia). To narrow down the number of modules that will be tested, specify a filename pattern after the -t option. For example, the following command searches for functioning PCMCIA modules that start with 3c:
modprobe -t /lib/modules/2. 2.14-3/pcmcia 3c*
If modprobe doesn’t succeed, don’t despair. Eventually, you’ll get one of the modules to work. However, you’ll have to specify module parameters.
Understanding module parameters
Some modules can load without needing any additional information. They can probe the device and find out which settings to use. For other modules, you may need to specify the module parameters. Module parameters are load-time statements that customize the module’s operation. Often, they consist of hardware settings, such as interrupt request (IRQ) and direct memory access (DMA) channels, which the module can’t determine automatically. If you plan on using a module that requires information about these hardware settings, you’ll need to determine the correct settings before you can use the module. To do so, check the adapter’s documentation. Unless you’re installing a Plug-and-Play device, you should also look at the adapter’s jumpers to see which configuration settings have been chosen.
It’s not enough to know the correct settings; you must also know how to type the module parameters. The format varies for each module, so you’ll need documentation. To obtain the documentation that you need in order to specify module parameters correctly, look for the module’s name in /usr/src/linux/Documentation. (For example, documentation on the sound modules would be found in /usr/src/linux/Documentation/sound.) You may need to do some detective work to find the information you need. For tips on locating the information that you need, open /usr/src/linux/Documentation/Configure.help and search for the module’s name.
Here’s an example of module parameters in action. To load the Iomega Zip Zoom SCSI adapter module, you would type a modprobe command like the following:
modprobe aha152x 0x340,12,7,1
This statement loads the aha152x module with the following configuration: the input/output port is 0x340, the IRQ is 12, the SCSI device ID is 7, and the reconnect setting is 1. If you type any of these settings incorrectly or if you supply settings that don’t correspond to the actual settings that the device uses, the module won’t load.
Specifying module configurations
If you plan on loading a particular module frequently, you’ll want to take advantage of modprobe’s ability to work with the /etc/conf.modules configuration file (also called /etc/modules.conf). This configuration file enables you to specify an alias for the module, and it enables you to specify the module parameters that you need in order to load the module successfully. The alias comes in handy when you’re using modprobe. Once you’ve defined the alias, you (or a script) can load the module and any module parameters that you’ve specified by typing modprobe and the alias. Here’s an example of a module configuration file for the Iomega Zip Zoom SCSI adapter that I mentioned above:
alias scsi_hostadapter aha152x
options scsi_hostadapter aha152x=0x340,12,7,1
The following example enables sound on a Dell Latitude CPi notebook computer that has a Crystal sound chip (which is compatible with the CS4232 driver) and a Yamaha MIDI synthesizer (which is compatible with the op13 driver):
alias sound cs4232
options cs4232 io=0x530 irq=7 dma=1 dma2=0
alias midi op13
options op13 io=0x388
Starting modules when you boot your system
When you boot your Linux system, a variety of startup scripts leaps into action. What they do, where they’re located, and what’s in them depend on a dizzying variety of factors, including the Linux distribution that you’re using and whether or not you’ve run any installation utilities. Still, there seem to be some common themes. For example, script authors usually assume that you’re using the following aliases to refer to modules in /etc/conf.modules and other configuration files:
- eth0: This is an alias for the first Ethernet network adapter in your system. (The second would be eth1).
- sound: In most Linux distributions, this is an alias for the sound module.
- midi: In most Linux distributions, this is an alias for the MIDI module.
If you stick to these aliases when you create /etc/conf.modules, the initialization scripts may find the modules that you’ve linked to these aliases and install them every time you boot. If this trick doesn’t work, there’s an easy alternative. In the directory /etc/rc.d, create a file named rc.modules. This script is referenced in /etc/rc.d/rc.sysinit, the main initialization script. The commands that it contains will be executed every time your system starts. Begin the file with #!/bin/sh so that the shell will know that it’s a script. The shell will list the modules that you want to load (one on each line). Here’s an example:
echo “Launching SLHC & PPP Modules…”
Both of these aliases (slhc and ppp) must have valid entries in /etc/conf.modules, or this script won’t work.
Now, you’re a master of modules. You’ve learned why modules exist, what they do, how they’re manipulated, and how they’re configured. To be sure, you’ll need lots of detailed information in order to get a specific module running, but you know where to look (/usr/src/linux/Documents/). After reading this Daily Drill Down, you should be able to solve module mysteries. And that means that you have a good chance of putting hardware installation hassles behind you.
Bryan Pfaffenberger, a UNIX user since 1985, is a University of Virginia professor, an author, and a passionate advocate of Linux and open-source software. A Linux Journal columnist, his recent Linux-related books include Linux Clearly Explained (Morgan-Kaufmann) and Mastering Gnome (Sybex; in press). His hobbies include messing around with his home LAN and sailing the southern Chesapeake Bay. He lives in Charlottesville, VA. If you’d like to contact Bryan, send him an e-mail.
The authors and editors have taken care in preparation of the content contained herein, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for any damages. Always have a verified backup before making any changes.