Configuring and Building the Kernel - System Administration - Running Linux, 5th Edition (2009)

Running Linux, 5th Edition (2009)

Part II. System Administration

Chapter 18. Configuring and Building the Kernel

Rebuilding the kernel sounds like a pastime for hackers, but it is an important skill for any system administrator. Rebuilding the kernel on your system to eliminate the device drivers you don't need is one good reason to do so. This reduces the amount of memory used by the kernel itself, as described in "Managing Swap Space" in Chapter 10. The kernel is always present in memory, and the memory it uses cannot be reclaimed for use by programs if necessary.

It should be noted here that most distributions today ship with modularized kernels . This means that the kernel they install by default contains only the minimum functionality needed to bring up the system; everything else is then contained in modules that add any additionally needed functionality on demand. We will talk about modules in much greater detail later. But even with these stripped-down kernels, distributions have to ship several versions, for example, in order to provide support for both single-processor and multiprocessor machines, as this is something so central that it cannot be moved into a module. The installers that come with distributions are typically smart enough to figure out which kernel you need and install the right one, however.

Why is the ability to select features a win for you? All kernel code and data are "locked down" in memory; that is, they cannot be swapped out to disk. For example, if you use a kernel image with support for hardware you do not have or use, the memory consumed by the support for that hardware cannot be reclaimed for use by user applications. Customizing the kernel allows you to trim it for your needs.

You also need to occasionally upgrade your kernel to a newer version. As with any piece of your system, if you know of important bug fixes or new features in a kernel release, you may want to upgrade to pick them up. Those people who are actively developing kernel code will also need to keep their kernel up-to-date in case changes are made to the code they are working on. Sometimes, it is necessary to upgrade your kernel to use a new version of the compiler or libraries. Some applications (such as the VMware emulator) require a certain kernel version to run.

You can find out what kernel version you are running through the command uname -a. This should produce something like the following:

rutabaga$ uname -a

Linux pooh 2.6.11.4-21.7-default #1 Thu Jun 2 14:23:14 UTC 2005 i686 i686 i386 GNU/Linux

Here, we see a machine running Version 2.6.11.4 of the kernel, which was last compiled on June 2, 2005. We see other information as well, such as the hostname of the machine, the number of times this kernel has been compiled (once), and the fact that the machine is a Pentium Pro or better (as denoted by i686). The manpage for uname(1) can tell you more.

Building a New Kernel

The Linux kernel is a many-tentacled beast. Many groups of people work on different pieces of it, and some parts of the code are a patchwork of ideas meeting different design goals. Overall, however, the kernel code is clean and uniform, and those interested in exploring its innards should have little trouble doing so. However, because of the great amount of development going on with the kernel, new releases are made very rapidly—sometimes daily! The chief reason for this is that nearly all device drivers are contained within the kernel code, and every time someone updates a driver, a new release is necessary. Even though almost all device drivers are loadable modules these days, they are still typically shipped together with the kernel as one big package.

Currently, Linus Torvalds maintains the "official" kernel release. Although the GPL allows anyone to modify and rerelease the kernel under the same copyright, Linus's maintenance of an "official" kernel is a helpful convention that keeps version numbers uniform and allows everyone to be on equal footing when talking about kernel revisions. In order for a bug fix or new feature to be included in the kernel, all one must do is send it to Linus (or whoever is in charge for the kernel series in question — Linus himself always maintains the most current kernel), who will usually incorporate the change as long as it doesn't break anything. Linus also makes use of so-called lieutenants, very experienced kernel developers, who take care of particular subsystems.

Kernel version numbers follow the convention

major.minor.patchlevel

major is the major version number, which rarely changes; minor is the minor version number, which indicates the current "strain" of the kernel release; and patchlevel is the number of the patch to the current kernel version. Some examples of kernel versions are 2.4.4 (patch level 4 of kernel Version 2.4), and 2.6.11.4 (subversion 4 of patch level 11 of kernel Version 2.6).

If you are interested in how the existing kernel versions have evolved, check out http://www.kernel.org.

On your system, the kernel sources most probably live in /usr/src/linux (unless you use the Debian distribution, where you can find the kernel sources in /usr/src/kernel-source-versionsnumber). If you are going to rebuild your kernel only from the current sources, you don't need to obtain any files or apply any patches (assuming you installed the kernel sources when you installed your system). If you wish to upgrade your kernel to a new version, you need to follow the instructions in the following section.

Obtaining Kernel Sources

The official kernel is released as a gzipped tar file, containing the sources along with a series of patch files—one per patch level. The tar file contains the source for the unpatched revision; for example, there is a tar file containing the sources for kernel Version 2.6.0 with no patches applied. Each subsequent patch level is released as a patch file (produced using diff), which can be applied using the patch program. In "Patching Files" in Chapter 21, we describe the use of patch in detail.

Let's say you're upgrading to kernel Version 2.6, patch level 4. You'll need the sources for 2.6 (the file might be named v2.6.0.tar.gz) and the patches for patch levels 1 through 4. These files would be named patch1, patch2, and so forth. (You need all the patch files up to the version to which you're upgrading. Usually, these patch files are rather small, and are gzipped on the archive sites.) All these files can be found in the kernel directory of the Linux FTP archive sites; for example, on ftp://ftp.kernel.org, the directory containing the 2.6 sources and patches is/pub/linux/kernel/v2.6. You will find the kernel sources here as tar archives, compressed with both gzip and bzip2.

If you are already at some patch level of the kernel (such as 2.6 patch level 2) and want to upgrade to a newer patch level, you can simply apply the patches from the version you have up to the version to which you'd like to upgrade. If you're upgrading from, say, 2.6 patch level 2 to 2.6 patch level 4, you need the patch files for 2.6.3 and 2.6.4.

Unpacking the sources

First, unpack the source tar file from /usr/src using commands such as:

rutabaga# cd /usr/src

rutabaga# mv linux linux.old

rutabaga#tar xzf v2.6.0.tar.gz

This saves your old kernel source tree as /usr/src/linux.old and creates /usr/src/linux containing the new sources. Note that the tar file containing the sources includes the linux subdirectory.

You should keep your current kernel sources in the directory /usr/src/linux because there are two symbolic links--/usr/include/linux and /usr/include/asm--that point into the current kernel source tree to provide certain header files when compiling programs. (If you are planning on doing any software development, you should always have your kernel sources available so that programs using these include files can be compiled.) If you want to keep several kernel source trees around, be sure that /usr/src/linux points to the most recent one.

Applying patches

If you are applying any patch files, use the patch program. Let's say that you have the files patch1.gz through patch4.gz, which are gzipped. These patches should be applied from the kernel sources main directory. That doesn't mean the patch files themselves should be located there, but rather that patch should be executed from, for example, /usr/src/linux. For each patch file, use the command:

gunzip -c patchfile | patch -p1

from /usr/src. The -p1 option tells patch it shouldn't strip any part of the filenames contained within the patch file except for the first one.

You must apply each patch in numerical order by patch level. This is very important. Note that using a wildcard such as patch* will not work because the * wildcard uses ASCII order, not numeric order. (Otherwise, if you are applying a larger number of patches, patch1 might be followed bypatch10 and patch11, as opposed to patch2 and patch3.) It is best to run the previous command for each patch file in succession, by hand. This way you can ensure you're doing things in the right order.

You shouldn't encounter problems when patching your source tree in this way unless you try to apply patches out of order or apply a patch more than once. Check the patch manual page if you do encounter trouble. If all else fails, remove the new kernel source tree and start over from the original tar file.

To double-check that the patches were applied successfully, use the commands:

find /usr/src/linux -follow -name "*.rej" -print

find /usr/src/linux -follow -name "*#" -print

This lists any files that are "rejected" portions of the patch process. If any such files exist, they contain sections of the patch file that could not be applied for some reason. Look into these, and if there's any doubt, start over from scratch. You cannot expect your kernel to compile or work correctly unless the patch process completes successfully and without rejections.

A handy script for patching the kernel is available and can be found in scripts/patch-kernel. But as always, you should know what you are doing before using automated tools — even more so when it comes to the very core of the operating system, the kernel.

Building the Kernel

There are six steps to building the kernel, and they should be quite painless. All these steps are described in more detail in the following pages.

1. Make sure that all the required tools and utilities are installed and at the appropriate versions. See the file Documentation/Changes in the kernel source for the list of requirements.

2. Run make config, which asks you various questions about which drivers you wish to include. You could also use the more comfortable variants make menuconfig, or make xconfig (when you are running KDE), or make gconfig (when you are running GNOME).

If you have previously built a kernel and then applied patches to a new version, you can run make oldconfig to use your old configuration but be prompted for any new options that may not have been in the old kernel.

3. Some older kernels require you at this point to run make dep to gather dependencies for each source file and include them in the various makefiles. This step is not necessary for current kernels (such as the 2.6 series).

4. If you have built a kernel from this source tree before, run make clean to clear out old object files and force a complete rebuild.

5. Run make bzImage to build the kernel itself.

6. Go have a coffee (or two, depending on the speed of your machine and amount of available memory).

7. Install the new kernel image, either on a boot floppy or via GRUB. You can use make bzDisk to put the kernel on a boot floppy.

All these commands are executed from /usr/src/linux, except for step 5, which you can do anywhere.

A README file is included in the kernel sources, which should be located at /usr/src/linux/README on your system. Read it. It contains up-to-date notes on kernel compilation, which may be more current than the information presented here. Be sure to follow the steps described there, using the descriptions given later in this section as a guide. If you have installed the kernel sources from a package included with your distribution, there may also be a file with distribution-specific notes that tells you how your distribution's packagers have configured the kernel, and whether (and how) the kernel changes have been changed from the pristine sources that you can download from the net.

Kernel configuration: make config

The first step is to run make config. This executes a script that asks you a set of yes/no questions about which drivers to include in the kernel. There are defaults for each question, but be careful: the defaults probably don't correspond to what you want. (When several options are available, the default will be shown as a capital letter, as in [Y/n].) Your answers to each question will become the default the next time you build the kernel from this source tree.

Simply answer each question, either by pressing Enter for the default, or pressing y or n (followed by Enter). Some questions don't have a yes/no answer; you may be asked to enter a number or some other value. A number of the configuration questions allow an answer of m in addition to yor n. This option allows the corresponding kernel feature to be compiled as a loadable kernel module, as opposed to building it into the kernel image itself. Loadable modules, covered in the following section, "Loadable Device Drivers," allow portions of the kernel (such as device drivers) to be loaded and unloaded as needed on a running system. If you are unsure about an option, type ? at the prompt; for most options, a message will be shown that tells you more about the option.

The system remembers your configuration options each time you run make config, so if you're adding or removing only a few features from your kernel, you need not re-enter all the options.

Some people say that make config has so many options now that it is hardly feasible to run it by hand any longer, as you have to concentrate for a long time to press the right keys in response to the right questions. Therefore, people are moving to the alternatives described next.

An alternative to running make config is make xconfig, which compiles and runs an X-Window-based kernel configuration program. In order for this to work, you must have the X Window System running, have the appropriate X11 and Qt libraries installed, and so forth. Instead of asking a series of questions, the X-based configuration utility allows you to use checkboxes to select which kernel options you want to enable.

Also available is make menuconfig, which uses the text-based curses library, providing a similar menu-based kernel configuration if you don't have X installed. make menuconfig and make xconfig are much more comfortable than make config, especially because you can go back to an option and change your mind up to the point where you save your configuration. However, we'll describe the process here in a linear fashion, as make config does it.

The following is part of a session with make config. When using make menuconfig or make xconfig, you will encounter the same options, only presented in a more user-friendly fashion (we actually recommend the use of these tools if at all possible, because it is very easy to get confused by the myriad of configuration options):

pooh:/usr/src/linux # make config

scripts/kconfig/conf arch/i386/Kconfig

#

# using defaults found in .config

#

*

* Linux Kernel Configuration

*

*

* Code maturity level options

*

Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?]

Select only drivers expected to compile cleanly (CLEAN_COMPILE) [Y/n/?]

*

* General setup

*

Local version - append to kernel release (LOCALVERSION) [-default]

Support for paging of anonymous memory (swap) (SWAP) [Y/n/?]

System V IPC (SYSVIPC) [Y/n/?]

POSIX Message Queues (POSIX_MQUEUE) [Y/n/?]

BSD Process Accounting (BSD_PROCESS_ACCT) [Y/n/?]

BSD Process Accounting version 3 file format (BSD_PROCESS_ACCT_V3) [Y/n/?]

Sysctl support (SYSCTL) [Y/n/?]

Auditing support (AUDIT) [Y/n/?]

Enable system-call auditing support (AUDITSYSCALL) [Y/n/?]

Kernel log buffer size (16 => 64KB, 17 => 128KB) (LOG_BUF_SHIFT) [17]

Support for hot-pluggable devices (HOTPLUG) [Y/?] y

Kernel Userspace Events (KOBJECT_UEVENT) [Y/n/?]

Kernel .config support (IKCONFIG) [Y/n/?]

Enable access to .config through /proc/config.gz (IKCONFIG_PROC) [Y/n/?]

*

* Configure standard kernel features (for small systems)

*

Configure standard kernel features (for small systems) (EMBEDDED) [N/y/?]

Load all symbols for debugging/kksymoops (KALLSYMS) [Y/?] (NEW) y

Include all symbols in kallsyms (KALLSYMS_ALL) [N/y/?]

Do an extra kallsyms pass (KALLSYMS_EXTRA_PASS) [N/y/?]

*

* Loadable module support

*

Enable loadable module support (MODULES) [Y/n/?]

Module unloading (MODULE_UNLOAD) [Y/n/?]

Forced module unloading (MODULE_FORCE_UNLOAD) [Y/n/?]

Module versioning support (EXPERIMENTAL) (MODVERSIONS) [Y/n/?]

Source checksum for all modules (MODULE_SRCVERSION_ALL) [Y/n/?]

Automatic kernel module loading (KMOD) [Y/n/?]

*

* Processor type and features

*

Subarchitecture Type

> 1. PC-compatible (X86_PC)

2. AMD Elan (X86_ELAN)

3. Voyager (NCR) (X86_VOYAGER)

4. NUMAQ (IBM/Sequent) (X86_NUMAQ)

5. SGI 320/540 (Visual Workstation) (X86_VISWS)

choice[1-5]:

Processor family

1. 386 (M386)

2. 486 (M486)

> 3. 586/K5/5x86/6x86/6x86MX (M586)

4. Pentium-Classic (M586TSC)

5. Pentium-MMX (M586MMX)

6. Pentium-Pro (M686)

7. Pentium-II/Celeron(pre-Coppermine) (MPENTIUMII)

8. Pentium-III/Celeron(Coppermine)/Pentium-III Xeon (MPENTIUMIII)

9. Pentium M (MPENTIUMM)

10. Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon (MPENTIUM4)

11. K6/K6-II/K6-III (MK6)

12. Athlon/Duron/K7 (MK7)

13. Opteron/Athlon64/Hammer/K8 (MK8)

14. Crusoe (MCRUSOE)

15. Efficeon (MEFFICEON)

16. Winchip-C6 (MWINCHIPC6)

17. Winchip-2 (MWINCHIP2)

18. Winchip-2A/Winchip-3 (MWINCHIP3D)

19. CyrixIII/VIA-C3 (MCYRIXIII)

20. VIA C3-2 (Nehemiah) (MVIAC3_2)

choice[1-20]:

Generic x86 support (X86_GENERIC) [Y/n/?]

HPET Timer Support (HPET_TIMER) [N/y/?]

Symmetric multi-processing support (SMP) [N/y/?]

Preemptible Kernel (PREEMPT) [N/y/?]

Local APIC support on uniprocessors (X86_UP_APIC) [Y/n/?]

IO-APIC support on uniprocessors (X86_UP_IOAPIC) [Y/n/?]

Disable local/IO APIC by default (X86_APIC_OFF) [Y/n/?]

Machine Check Exception (X86_MCE) [Y/n/?]

Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4 (X86_MCE_NONFATAL)

[N/m/y/?]

check for P4 thermal throttling interrupt. (X86_MCE_P4THERMAL) [Y/n/?]

Toshiba Laptop support (TOSHIBA) [M/n/y/?]

...and so on...

*** End of Linux kernel configuration.

*** Check the top-level Makefile for additional configuration.

*** Next, you may run 'make bzImage', 'make bzdisk', or 'make

install'.

If you have gathered the information about your hardware when installing Linux, that information is probably sufficient to answer the configuration questions, most of which should be straightforward. If you don't recognize some feature, it's a specialized feature that you don't need.

It should be noted here that not all Linux device drivers are actually built into the kernel. Instead, some drivers are available only as loadable modules, distributed separately from the kernel sources. (As mentioned earlier, some drivers can be either built into the kernel or compiled as modules. In other cases, you have only one choice or the other.)

If you can't find support for your favorite hardware device in the list presented by make config, it's quite possible that the driver is available as a module or a separate kernel patch. Scour the FTP sites and archive CD-ROMs if you can't find what you're looking for. In the next section, "Loadable Device Drivers," kernel modules are covered in detail.

The following questions are found in the kernel configuration for Version 2.6.11.4. If you have applied other patches, additional questions might appear. The same is true for later versions of the kernel. Note that in the following list we don't show all the kernel configuration options; there are simply too many of them, and most are self-explanatory. We have highlighted only those that may require further explanation. Remember that if you're not sure how to answer a particular question, the default answer is often the best choice. When in doubt, it is also a good idea to type ? and check the help message.

Following are the high-level choices and the ramifications of choosing each one.

Prompt for development and/or incomplete code/drivers

Answer yes for this item if you want to try new features that aren't considered stable enough by the developers. You do not want this option unless you want to help test new features.

System V IPC

Answering yes to this option includes kernel support for System V interprocess communication (IPC) functions, such as msgrcv and msgsnd. Some programs ported from System V require this; you should answer yes unless you have a strong aversion to these features.

Sysctl support

This option instructs the kernel to provide a way to change kernel parameters on the fly, without rebooting. It is a good idea to enable this unless you have very limited memory and cannot tolerate the extra 8 KB that this option adds to the kernel.

Enable loadable module support

This enables the support for dynamically loading additional modules. You definitely want to enable this.

Module versioning support

This is a special option that makes it possible to use a module compiled for one kernel version with another kernel version. A number of problems are attached to this; say no here unless you know exactly what you are doing.

Automatic kernel module loading

If you enable this option, the kernel can automatically load and unload dynamically loadable modules as needed.

Processor family (20 different choices currently) [586/K5/5x86/6x86/6x86MX]

Here, you have to specify the CPU type that you have. The kernel will then be compiled with optimizations especially geared toward your machine. Note that if you specify a higher processor here than you actually have, the kernel might not work. Choosing an earlier CPU type (such as a Pentium when what you actually have is a Pentium IV) should work just fine, but your kernel may not run as fast as it could when using more advanced machine-specific features available in newer CPUs.

Symmetric multi-processing support

This enables kernel support for more than one CPU. If your machine has more than one CPU, say yes here; if not, say no.

Power management options (ACPI, APM)

This is an entire subsection for power management, mostly for laptops, but things like suspend-to-disk ("hibernation") could be useful for workstations too. However, power management often leads to problems, including a complete failure to boot. If you experience any problems, try recompiling your kernel without power management, or pass the kernel command-line options noapm and noacpi at boot time to turn off power management.

PCI support

Enable this option if your motherboard includes the PCI bus and you have PCI-bus devices installed in your system. The PCI BIOS is used to detect and enable PCI devices; kernel support for it is necessary for use of any PCI devices in your system.

Parallel port support

Enable this option if you have a parallel port in your system and want to access it from Linux. Linux can use the parallel port not only for printers, but also for PLIP (a networking protocol for parallel lines), Zip drives, scanners, and other things. In most cases, you will need an additional driver to attach a device to the parallel port. If you have a modern printer that reports status back to the computer, you also want to enable the IEEE 1284 transfer modes option.

Normal floppy disk support

Answer yes to this option unless you don't want support for floppy drives (this can save some memory on systems where floppy support isn't required). If you are using one of those attachable floppy drives on IBM Thinkpad laptops, you also need to pass floppy=thinkpad to the kernel at boot time.

Parallel port IDE device support

This option enables support for IDE devices that are attached to the parallel port, such as portable CD-ROM drives.

Packet writing on CD/DVD media

If you have a modern CD or DVD burner, you can enable packet writing (as opposed to track writing) here by selecting this option.

Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support

Answer yes to this option unless you don't need IDE/MFM/RLL drive support. After answering yes, you will be prompted for types of devices (hard disks, CD-ROM drives, tape drives, and floppy drives) you want to access over the IDE driver. If you have no IDE hardware (only SCSI), it may be safe to disable this option.

SCSI support

If you have a SCSI controller of any kind, answer yes to this option. You will be asked a series of questions about the specific SCSI devices on your system; be sure you know what type of hardware you have installed. All these questions deal with specific SCSI controller chips and boards; if you aren't sure what sort of SCSI controller you have, check the hardware documentation or consult the Linux HOWTO documents.

You will also be asked if you want support for SCSI disks, tapes, CD-ROMs, and other devices; be sure to enable the options appropriate for your hardware.

If you don't have any SCSI hardware, you should answer no to this option; it greatly reduces the size of your kernel.

Old CD-ROM drivers

This is a series of questions dealing with the specific CD-ROM drivers supported by the kernel, such as the Sony CDU31A/33A, Mitsumi, or Sound Blaster Pro CD-ROM. If you have a SCSI or IDECD-ROM controller (and have selected support for it earlier), you need not enable any of these options. Some CD-ROM drives have their own interface boards, and these options enable drivers for them.

Networking support

Answer yes to this option if you want any sort of networking support in your kernel (including TCP/IP, SLIP, PPP, NFS, and so on).

Networking options

If you selected networking support, you will be asked a series of questions about which networking options you want enabled in your kernel. Unless you have special networking needs (in which case you'll know how to answer the questions appropriately), selecting the defaults for these questions should suffice. A number of the questions are esoteric in nature (such as PF_KEY sockets), and you should select the defaults for these in almost all cases.

Network device support

This is a series of questions about the specific networking controllers Linux supports. If you plan to use an Ethernet card (or some other networking controller), be sure to enable the options for your hardware. As with SCSI devices, you should consult your hardware documentation or the Linux HOWTO documents (such as the Ethernet HOWTO) to determine which driver is appropriate for your network controller.

Amateur Radio support

This option enables basic support for networking over public radio frequencies. If you have the equipment to use the feature, enable this option and read the AX25 and the HAM HOWTO.

ISDN subsystem

If you have ISDN hardware in your system, enable this option and select the ISDN hardware driver suitable for your hardware. You will most probably also want to select Support synchronous PPP (see "PPP over ISDN" in Chapter 13). Linux is currently switching from the old so-called ISDN4Linux support to support of the CAPI 2.0 standard. Both should work with most ISDN hardware, but CAPI 2.0 support is going to be used exclusively in the future.

Telephony support

Linux supports some interface cards that let you use a normal telephone set with VoIP (voice-over-IP) Internet telephony . As the documentation says, this has nothing to do with modems, so you have to enable this only if you have such an interface card.

Character devices

Linux supports a number of special "character" devices, such as serial and parallel port controllers, tape drives, and mice with their own proprietary interfaces (not mice that connect to the serial and USB ports, such as the Microsoft serial mouse) or most newer mice.

Sound

This section lets you pick between two different sound systems, the newer ALSA (Advanced Linux Sound Architecture) and the older OSS (Open Sound System). If it supports your sound hardware, go for ALSA.

USB support

Enable this to get support for many USB devices. In particular, if you want to use the popular memory sticks, you need to select USB Mass Storage Support as well. This option also applies to digital cameras that are connected to your computer via the USB port.

Filesystems

This is a series of questions for each filesystem type supported by the kernel. As discussed in the section "Managing Filesystems" in Chapter 10, a number of filesystem types are supported by the system, and you can pick and choose which to include in the kernel. Nearly all systems should include support for the Second Extended and /proc filesystems. You should include support for the MS-DOS filesystem if you want to access your MS-DOS files directly from Linux, and the ISO 9660 filesystem to access files on a CD-ROM (most of which are encoded in this way).

Kernel hacking

This section contains options that are useful only if you plan on hacking the Linux kernel yourself. If you do not want to do this, answer no.

Preparing the ground: make clean

If you wish to force a complete recompilation of the kernel, you should issue make clean at this point. This removes from this source tree all object files produced from a previous build. If you have never built the kernel from this tree, you're probably safe skipping this step (although it can't hurt to perform it). If you are tweaking minor parts of the kernel, you might want to avoid this step so that only those files that have changed will be recompiled. At any rate, running make clean simply ensures the entire kernel will be recompiled "from scratch," and if you're in any doubt, use this command to be on the safe side.

Compiling the kernel

Now you're ready to compile the kernel. This is done with the command make bzImage. It is best to build your kernel on a lightly loaded system, with most of your memory free for the compilation. If other users are accessing the system, or if you're trying to run any large applications yourself (such as the X Window System, or another compilation), the build may slow to a crawl. The key here is memory. If a system is low on memory and starts swapping, it will be slow no matter how fast the processor is.

The kernel compilation can take anywhere from a few minutes to many hours, depending on your hardware. There is a great deal of code—well over 80 MB—in the entire kernel, so this should come as no surprise. Slower systems with 16 MB (or less) of RAM can expect to take several hours for a complete rebuild; faster machines with more memory can complete it in less than half an hour. Your mileage will most assuredly vary.

If any errors or warnings occur while compiling , you cannot expect the resulting kernel to work correctly; in most cases, the build will halt if an error occurs. Such errors can be the result of incorrectly applying patches, problems with the make config step, or actual bugs in the code. In the "stock" kernels , this latter case is rare, but is more common if you're working with development code or new drivers under testing. If you have any doubt, remove the kernel source tree altogether and start over.

When the compilation is complete, you will be left with the file bzImage in the directory /usr/src/linux/arch/i386/boot. (Of course, if you're attempting to build Linux on a platform other than the Intel x86, the kernel image will be found in the corresponding subdirectory under arch.) The kernel is so named because it is the executable image of the kernel, and it has been internally compressed using the bzip2 algorithm. When the kernel boots, it uncompresses itself into memory: don't attempt to use bzip2 or bunzip2 on bzImage yourself! The kernel requires much less disk space when compressed in this way, allowing kernel images to fit on a floppy. Earlier kernels supported both the gzip and the bzip2 compression algorithms, the former resulting in a file called zImage. Because bzImage gives better compression results, however, gzip should not be used, as the resulting kernels are usually too big to be installed these days.

If you pick too much kernel functionality, you can get a kernel too big error at the end of the kernel compilation. This happens rarely because you need only a very limited amount of hardware support for one machine, but it can happen. In this case, there is one way out: compile some kernel functionality as modules (see "Loadable Device Drivers").

You should now run rdev on the new kernel image to verify that the root filesystem device, console SVGA mode, and other parameters have been set correctly. This is described in "Using a Boot Floppy" in Chapter 17.

Installing the kernel

With your new kernel in hand, you're ready to configure it for booting. This involves either placing the kernel image on a boot floppy, or configuring GRUB to boot the kernel from the hard drive. These topics are discussed in "Booting the System" in Chapter 17. To use the new kernel, configure it for booting in one of these ways, and reboot the system.

Warning

You should always keep a known good kernel available for booting. Either keep a previous backup kernel selectable from GRUB or test new kernels using a floppy first. This will save you if you make a mistake such as omitting a crucial driver in your new kernel, making your system not bootable.

Loadable Device Drivers

Traditionally, device drivers have been included as part of the kernel. There are several reasons for this. First of all, nearly all device drivers require the special hardware access provided by being part of the kernel code. Such hardware access can't be obtained easily through a user program. Also, device drivers are much easier to implement as part of the kernel; such drivers have complete access to the data structures and other routines in the kernel and can call them freely.

A conglomerate kernel containing all drivers in this manner presents several problems. First of all, it requires the system administrator to rebuild the kernel in order to selectively include device drivers, as we saw in the previous section. Also, this mechanism lends itself to sloppy programming on the part of the driver writers: there's nothing stopping a programmer from writing code that is not completely modular—code which, for example, directly accesses data private to other parts of the kernel. The cooperative nature of the Linux kernel development compounds this problem, and not all parts of the code are as neatly contained as they should be. This can make it more difficult to maintain and debug the code.

In an effort to move away from this paradigm, the Linux kernel supports loadable device drivers —device drivers that are added to or removed from memory at runtime, with a series of commands. Such drivers are still part of the kernel, but they are compiled separately and enabled only when loaded. Loadable device drivers, or modules, are generally loaded into memory using commands in one of the boot-time rc scripts.

Modules provide a cleaner interface for writing drivers. To some extent, they require the code to be somewhat modular and to follow a certain coding convention. (Note that this doesn't actually prevent a programmer from abusing the convention and writing nonmodular code. Once the module has been loaded, it is just as free to wreak havoc as if it were compiled directly into the kernel.) Using modules makes drivers easier to debug; you can simply unload a module, recompile it, and reload it without having to reboot the system or rebuild the kernel as a whole. Modules can be used for other parts of the kernel, such as filesystem types, in addition to device drivers.

Most device drivers, and a lot of other kernel functionality under Linux, are implemented as modules. One of them is the parallel port driver for PCs (or parport_pc driver), for devices that connect to the parallel port (there are also additional drivers for special devices such as printers that report back status to the computer). If you plan to use this driver on your system, it is good to know how to build, load, and unload modules. Although nothing is stopping you from compiling this module statically into your kernel, a parallel port driver is something that you need only rarely (whenever you print to a directly connected printer, maybe a couple of times a day), and its driver shouldn't occupy valuable RAM during the times it is not needed. See the Linux Printing HOWTO for more about parallel port printing.

Installing the Kernel

Now we'll talk about how to load and unload modules from the kernel. The first thing you'll need is the module-init-tools package, which contains the commands used to load and unload modules from the kernel. On the FTP archive sites, this is usually found as module-init-tools-versionnumber.tar.bz2 in the directory where the kernel sources are kept. This package contains the sources to the commands insmod, modprobe, rmmod, and lsmod. All reasonably recent Linux distributions include these commands (found in sbin) already, so if you already have these commands installed, you probably don't need to get the modules package. However, it can't hurt to get the package and rebuild these commands to be sure that you have the most up-to-date version.

To rebuild these commands, unpack module-init-tools-versionnumber.tar.bz2 (say, in a subdirectory of /usr/src). Follow the installation instructions contained there; usually all you have to do is execute make followed by make install (as root). The three commands will now be installed in/sbin and will be ready to use.

Compiling Modules

A module is simply a single object file containing all the code for the driver. For example, the parport_pc module might be called parport_pc.ko. On most systems, the modules themselves are stored in a directory tree below /lib/modules /kernelversion, where you can find different directories for the various types of modules. For example, the modules compiled for the 2.6.8 kernel would be below /lib/modules/2.6.8. You might already have a number of modules on your system; check the appropriate directory. Notice that kernel modules, unlike other compiled object files, have the filename extension .ko to show their status as kernel modules. If you are running an older version of Linux, your modules might still have the extension .o.

Modules can be either in the kernel sources or external to it. The former is the case for those device drivers, filesystems, and other functionality that are used most often and are maintained as part of the official kernel sources. Using these modules is very easy: during the make config, make menuconfig, or make xconfig step, select to build a certain feature as a module. Repeat this for everything you want to compile as a module. Then, after the make bzImage step, execute the following commands:

# make modules

#make modules_install

This will compile the modules and install them in /lib/modules/kernelversion.

New modules that are not yet integrated into the official kernel sources, or those that are simply too esoteric to be put into the kernel sources (e.g., a device driver for some custom-built hardware that is not publicly available) can be available as stand-alone, external modules. Unpack the archive of the module, compile it according to the instructions that are hopefully included, and copy the resulting module file to the appropriate subdirectory of /lib/modules/kernelversion. Some modules might have an install script or allow you to issue the command make install to perform the last step.

Loading a Module

Once you have a compiled module (either from the kernel sources or external), you can load it using the command:

insmod module

where module is the name of the module object file. For example:

insmod /lib/modules/2.6.11.4/kernel/drivers/parport/parport_pc.ko

installs the parport_pc driver if it is found in that file.

Once a module is installed, it may display some information to the console (as well as to the system logs), indicating that it is initialized. For example, the ftape driver might display the following:

Jul 26 13:08:41 tigger kernel: pnp: Device 00:09 activated.

Jul 26 13:08:41 tigger kernel: parport: PnPBIOS parport detected.

Jul 26 13:08:41 tigger kernel: parport0: PC-style at 0x378, irq 7 [PCSPP,TRISTATE]

The exact messages printed depend on the module, of course. Each module should come with ample documentation describing just what it does and how to debug it if there are problems.

It is likely that insmod will tell you it could not load the module into the kernel because there were "symbols missing ." This means that the module you want to load needs functionality from another part of the kernel that is neither compiled into the kernel nor contained in a module already loaded. In particular, the parport_pc module that we have been using as an example depends on the parport module that provides the general parallel port functionality. You could now try to find out which module contains those functions, load that module first with insmod, and try again. You will eventually succeed with this method, but it can be cumbersome, and this would not be Linux if there weren't a better way.

You first need a module database in the file /lib/modules/kernelversion/modules.dep. You can create this database by calling:

depmod -a

This goes through all the modules you have and records whether they need any other modules. With this database in place, you can simply replace the insmod command with the modprobe command, which checks the module database and loads any other modules that might be needed before loading the requested module. For example, our modules.dep file contains—among others—the following line:

/lib/modules/2.6.8/kernel/drivers/isdn/i4l/isdn.ko:/lib/modules/2.6.8/

kernel/drivers/net/slhc.ko

This means that in order to load the isdn module (a device driver for ISDN support), the slhc module (containing one of the ISDN protocol implementations) must be loaded. If we now load the isdn module with modprobe (this example is slightly simplified because the isdn module needs additional parameters):

modprobe hisax

modprobe will detect the dependency and load the slhc module. If you have compiled a module for the current kernel, you first need to run depmod -a, though, so that modprobe can find it.

Some modules need so-called module parameters. For example, a device driver might need to be assigned an IRQ. You can pass those parameters in the form parameter_name=parameter_value with both the insmod and the modprobe command. In the following example, several parameters are passed to the hisax module, which is a particular (and somewhat outdated) driver for a family of ISDN boards:

tigger # modprobe hisax type=3 protocol=2 io=0x280 irq=10

The documentation for each module should tell you which parameters the module supports. If you are too lazy to read the documentation, a nifty tool you can use is modinfo, which tells you—among other things—which parameters are accepted by the module you specify.

One caveat about modules if you use the Debian distribution: Debian uses a file called /etc/modules that lists the modules that should be loaded at boot time. If a module that you do not want keeps reappearing, check whether it is listed here.

You can list the drivers that are loaded with the command lsmod:

rutabaga$ lsmod

Module Size Used by

parport 40392 1 parport_pc

The memory usage of the module in bytes is displayed as well. The parport driver here is using about 40 KB of memory. If any other modules are dependent on this module, they are shown in the third column.

A module can be unloaded from memory using the rmmod command, as long as it is not in use. For example:

rmmod parport_pc

The argument to rmmod is the name of the driver as it appears in the lsmod listing.

Once you have modules working to your satisfaction, you can include the appropriate insmod commands in one of the rc scripts executed at boot time. One of your rc scripts might already include a place where insmod commands can be added, depending on your distribution.

One feature of the current module support is that you must rebuild a module any time you upgrade your kernel to a new version or patch level. (Rebuilding your kernel while keeping the same kernel version doesn't require you to do this.) This is done to ensure that the module is compatible with the kernel version you're using. If you attempt to load a module with a kernel that is newer or older than that for which it was compiled, insmod will complain and not allow the module to be loaded. When rebuilding a module, you must be running the kernel under which it will be used. Therefore, when upgrading your kernel, upgrade and reboot the new kernel first, then rebuild your modules and load them. There is an option that allows you to keep your modules when switching kernels, but a number of problems are associated with it, and we recommend against using it.

Loading Modules Automatically

The automatic loading of modules is an especially useful feature implemented by a kernel component called kmod . With the help of kmod, the kernel can load needed device drivers and other modules automatically and without manual intervention from the system administrator. If the modules are not needed after 60 seconds, they are automatically unloaded as well.

In order to use kmod, you need to turn on support for it (Automatic kernel module loading) during kernel configuration in the Loadable module support section.

Modules that need other modules must be correctly listed in /lib/modules /kernelversion/modules.dep, and there must be aliases for the major and minor number in /etc/modprobe.conf (and often in subdirectories of /etc/modprobe.d). See the documentation from the module-init-toolspackage for further information.

If a module has not been loaded manually with insmod or modprobe, but was loaded automatically by the kernel, the module is listed with the additional string (autoclean) in the lsmod output. This tells you that the kernel will remove the module if it has not been used for more than one minute.

We have gone through quite a lot of material now, and you should have all the tools you'll need to build and maintain your own kernels.