This month, we'll look at the process of building a Linux kernel in detail. We'll be using a Red Hat system as our example. Although the kernels that are included with the various Linux distributions do in fact work well in most circumstances, there are several situations in which you might want to build a customized kernel:
This month, we’ll look at the process of building a Linux kernel in detail. We’ll be using a Red Hat system as our example. Although the kernels that are included with the various Linux distributions do in fact work well in most circumstances, there are several situations in which you might want to build a customized kernel:
* You have added new hardware to the system which is not supported by or enabled in the current kernel.
* You want to use some operating system facility or software package for which kernel support is disabled by default. In this case, you would want to build a new kernel that had the corresponding kernel settings enabled.
* You want to use a smaller kernel image in order to save on disk space. When disk resources are scarce on a system, building a kernel that contains support for only those features that you are actually using on that computer can save a significant amount of space.
* You want to install a software package or other facility which requires changes to the kernel in order to work properly.
* You want to try out the latest-and-greatest Linux kernel. In this case, you will have to build it yourself, since major distribution vendor-supplied kernels tend to lag behind the cutting edge by a substantial amount, and vendor-provided kernel updates are, unfortunately, few and far between. We’ll have a bit more to say about this case at the end of the article.
Fortunately, building a Linux kernel is very easy. We’ll go through each of the steps in sequence.
Before you can begin to build a new kernel, several prerequisites must be met. You must have a development environment set up on your computer (e.g., C compiler and so on). You must also have installed the source code for the kernel headers (usually installed by default) and the kernel itself (not usually installed).
On a Red Hat Linux system, you can determine whether the kernel headers and source code are installed or not via this rpm command:
# rpm –query -a | grep kernel
The example output indicates that both packages are present on this system. If the kernel sources are not present, then you can install them by mounting the CD containing the source RPMs and then executing a command like the following:
rpm –install /cdlocation/SRPMS/kernel-source-2.2.X.i386.rpm
where cdlocation is the mount point for /dev/cdrom and X completes the kernel version number. The i386 portion of the filename will also be replaced by the corresponding abbreviation for other architectures on those systems.
Alternatively, you can download the kernel sources from the Internet and then just unpack the tar file in the usual manner.
When the sources are installed, they are generally found in a directory named /usr/src/linux-2.2.x. Conventionally, the directory /usr/src/linux is a symbolic link to the target kernel source tree. Usually, this link is automatically created when you install the source RPM, but in some cases, you may need to create it manually (or just change its target from an older kernel source tree).
You begin the kernel build process by changing to the topmost directory in the kernel source tree:
If you need to apply any patches to the kernel source, you do so with a command like this one:
# zcat /patch-location/patchN.gz | patch -p0 -e
where N is the patch number. Patches are generally needed only when adding additional software facilities obtained from the Internet.
The next step is to save any existing configuration files and then thoroughly clean up the kernel source tree:
# cp .config .config.save
# make mrproper
If this is your first time building a kernel from this source code, then the file .config may not exist (we’ll have more to say about it in a moment). Linux trivia question: can anyone tell me what mrproper stands for?
Configuring the Kernel
The next step is to specify the desired characteristics of the kernel, indicating what hardware and software support should be included within it. This step is automated, and you have a choice of three methods for accomplishing it, depending on the parameter you include on the next make command:
# make config –or–
# make menuconfig –or–
# make xconfig
All three of these commands will create the file .config in the current directory. This file specifies the settings of a large number of system variables which control various aspects of kernel behavior and hardware/software support. The make config command will take you through each option using a series of text prompts; its disadvantage is that if you change your mind about a setting after its prompt has gone by, you have to start over at the beginning in order to modify it again.
|Figure One: You can configure your kernel in a GUI with the make xconfig utility.|
|Figure Two: The make xconfig general setup panel and help facility.|
The make menuconfig and make xconfig commands accomplish the same task using a text-based and graphics X-based menu utility (respectively). Figure One illustrates make xconfig‘s main menu (pg. 80).
This tool divides all the available kernel configuration settings into a series of categories organized around the system facility to which they apply. Figure Two illustrates the General Setup category’s window.
Each of the items we see here can be set to “y” or “n” (yes or no) to enable or disable it, respectively. In addition, make xconfig provides help for any available item. In the illustration, the help for the PCI Quirks item is also displayed. The help window gives a brief description of the item as well as some advice on what settings should be selected, useful for the less experienced administrator.
The Next and Prev buttons at the bottom of each window will take you directly to the next or previous settings group without having to return to the tool’s main menu. In contrast, the Main Menu button closes the dialog and returns you (strangely enough) to the main menu.
Figure Three illustrates some of the panels used by the SCSI Support settings group. The first few items in the left window determine whether SCSI devices are supported at all by the kernel; in this case, SCSI support for all device types is enabled.
|Figure Three: The SCSI device settings in the make xconfig utility.|
Most of the settings illustrated in Figure Three have three possible values; “m” has been added to “y” and “n.” “m,” which stands for modules, indicates that support for the item should be enabled, but the actual functionality will be provided by a loadable module to the kernel rather than being compiled into the kernel image itself. Be aware that module support itself must also be enabled via the Loadable Module Support settings group (this support is generally turned on by default).
The righthand window in Figure Three illustrates the settings for the various supported SCSI adapters. It is reached via the SCSI low-level drivers button, the last item in the window on the left.
In our example, support for the Adaptec AIC7 adapter family has been enabled for module-based support (highlighted in red). When this setting is enabled, the following four settings are also enabled (highlighted in light blue); these may be used to specify AIC7-specific behavior.
Once you have set things up exactly the way you want them, you can use the buttons in the lower right corner of the main menu to complete this step. The Save and Exit and Quit Without Saving buttons work as expected. The other two buttons allow you to save a configuration to a file and to load one in from a saved file. Note that you still must save the settings to /usr/src/linux/.config for the kernel build to proceed as expected even if you save the settings somewhere else (this happens automatically when you Save and Exit).
Next, you will have to run two more make commands:
The first command creates files indicating the dependencies among various components in the kernel build process, and the second command removes any unneeded files from the source tree prior to the actual kernel compile (including all those that have been created by the build process thus far).
Building the Kernel
Now we are ready to actually build the kernel. The typical command to do so is:
This will produce a bzipped kernel executable file (i.e., compressed with bzip).
If you have added or modified any kernel modules or if this is the first time you have built the kernel from this source version, you must next build the module executables:
After this process completes, you may decide to save the previous versions of the kernel modules if you are building a new kernel with the same version number as the current kernel. You accomplish this by renaming the modules directory with a command like this one:
# mv /lib/modules/2.2.x /lib/modules/2.2.x.save
Once again, x completes the kernel version number.
Next, you must install the modules:
You must perform this step every time you build a module-enabled kernel, whether or not you have actually built any new modules, since it performs other required tasks needed for module support.
You are now ready to install the new kernel:
# cp /boot/vmlinuz /boot/ vmlinuz.save
#mvarch/i386/boot/bzImage / boot/new_vmlinuz
First, we make a copy of the old kernel (for paranoia’s sake). Then, we move the newly-built image to the /boot directory, calling it new_vmlinuz. In this way, we are doubly protected against a bad new kernel: we have both the old kernel and a copy of it.
At this point, add an entry to /etc/lilo.conf for the new kernel. An easy way to do so is to copy an existing entry and then change the label= and image= fields within it. Finally, run the lilo command to install the new configuration.
Getting It to Run
You are now ready to reboot and try out the new kernel. Don’t forget to enter the name you assigned it at the lilo prompt. If the system boots without any problems, then test out all of the system’s facilities. When you are ready to make the new kernel the default one, copy or move the new kernel to /boot/vmlinuz (or, if this file is a symbolic link, make the link point at the new kernel) and remove the old kernel file (but not the copy!) Then, edit /etc/lilo.conf again, removing the entry for the new kernel (which has become the default kernel) and adding one for the saved copy of the old, reliable kernel — just in case. Then run lilo again to install the configuration.
I hope this introductory overview has convinced you that building Linux kernels is easy and straightforward. I also happen to find it to be a quite enjoyable and satisfying process.
There are a few caveats you should be aware of with respect to the kernels included with Linux distributions. In many cases, the distribution creators will have modified the standard kernel source code. For example, they may choose to include packages in their distribution which require kernel modifications that they will have applied for you. This can be very helpful, but it also means that you can run into problems in two particular circumstances:
* If you try to build a new kernel from standard source code within a distribution where the vendor has made kernel modifications. In this case, you will need to manually apply whatever kernel patches the distribution relies on to the kernel source from which you build (common examples are the patches needed for the knfsd NFS server package).
* If you want to add additional software facilities which make significant modifications to the kernel code. In this case, the patches included with the software will assume standard kernel source code (i.e., as distributed), and they may fail to apply properly on vendor-modified kernel sources. If so, you will have to troubleshoot what went wrong (which requires a fair amount of programming expertise) or contact the distribution vendor for assistance.
For more information on building custom kernels, consult the Kernel-HOWTO (http://www.linuxdoc.org/HOWTO/Kernel-HOWTO.html). The documentation supplied with most commercial Linux distributions also includes information on building the kernel (for example, for Red Hat Linux, see the section “Building a Custom Kernel” in Chapter Two of the Official Red Hat Linux Reference Guide).
Æleen Frisch is the author of Essential System Administration. She can be reached at firstname.lastname@example.org.