Building a Linux Kernel

In our last issue, we looked at what data you need to collect before attempting to build a Linux kernel. This is very important information so you may want to take a look at the first article if you are a little rusty. I have also written an article about using the command line in Linux that may be helpful for you.

The first thing that you will probably need to do is unpack the kernel source in the /usr/src directory. The source does not have to be placed here, however this is the convention and the remainder of this article will assume that that is where you put it.

Before you actually unpack the source, make sure that there is not a directory or symlink to a directory named “linux”. A symlink (symbolic link) is very much like a shortcut. In the case of the kernel source code, you would use a symbolic link to point to the actual source code tree that you are using, especially if you have more than one source code tree (i.e. You may have several different versions of the kernel that you use. Rather than rename source code trees which can become confusing, use a symlink to point to the tree that you want to use).

If there is a directory named “linux” rename it to “linux-X.Y.Z”, where “X.Y.Z” is the actual version number of that kernel. If there is a symbolic link to a kernel source tree, simply delete it (from /usr/src/ type “rm linux”).

NOTE: I don’t know why they break from the convention of using “linux” as the directory name, but some distributions use variants of this name for the root of the Linux kernel source code tree (or the symlink to it). For instance, I know that RedHat 7.2 uses “linux-2.4”. If I am not mistaken, I seem to recall that both Mandrake and SuSE do something similar. Rather than have to worry about changing symbolic links in /usr/include, you may opt to leave this link named as is. You will still need to point it to your kernel source tree if you are not using the factory installed kernel source code. For the remainder of this article, I am assuming that your Linux kernel source code tree’s root is /usr/src/linux. If yours is not /usr/src/linux, you will have to make appropriate changes as necessary.

You will probably need to be ‘root’ for the commands found throughout the rest of this article to work. To do this, you can either log in as root (be careful, the system will let you do whatever you like, good or bad) or you can “su” to root.

Copy the tarball (compressed kernel source code file) that you downloaded to /usr/src/. I am going to assume that you have downloaded a *.tar.gz file for your kernel. If the kernel that you downloaded has a *.bz2 extension, refer to the man page for extracting (“man bunzip2” from the command line). If you are running a machine that has KDE installed, there is a nice “WinZipish” program known as Karchiver. This will extract most compressed file types.

Now you are ready to extract the kernel. At a command prompt in /usr/src simply type “tar xvzf linux-X.Y.Z.tar.gz” where X.Y.Z is the version number of the kernel. This will extract the kernel source to /usr/src/linux/. Rename the source directory to one including the version number and then create a symlink to the source tree. This is accomplished by entering the following while in the /usr/src directory:

mv linux linux-X.Y.Z #ln -s linux-X.Y.Z linux

Once the source is extracted, check out the /usr/src/linux/Documentation/changes file to verify that all of the tools (such as compilers, etc…) you will need to build the kernel are installed and up to date. This document explains how to check them and where to find them, if necessary.

You are now ready for the first two steps in building the kernel. Be sure to cd into /usr/src/linux first. Once you are in the /usr/src/linux directory, you will enter:

make mrproper

followed by:

make clean

Now you are ready to (gasp) configure the kernel. This is where all of your research will pay off. Have no fear if you think your knowledge of your hardware is not up to par. Most options are documented, or will at least point you to where you can find more information, so you will be able to make educated guesses about your configuration options.

You have your choice of several methods of configuring a kernel, based solely on your preference. The first, and by far most difficult, a method is to run “make config”. This is a console based method of configuration that will ask one question at a time until you have your kernel configured. Unless you have a good reason to use “make config”, don’t.

If for whatever reason, you do not have an X (graphical) desktop, you may use “make menuconfig”. This is an NCurses based configuration utility that is much more friendly than “make config”. If you are not sure that you have the NCurses library installed, try running “make menuconfig”. You won’t hurt anything if the NCurses library is not installed, it will just exit with errors.

Ideally, for configuration, you will have a working X server so that you can use “make xconfig”. This will provide a nice, intuitive kernel configuration utility complete with help buttons. For your first kernel, this is definitely the way to go.

I cannot go into actually configuring the kernel, because that is a subject that could fill a book. For your first kernel, you may want to build a kernel for an i386. This kernel should boot on any Intel-based machine (i.e. Intel, AMD, Cyrix, and, I suspect, VIA CPUs) that can run Linux. Later, as you become more familiar with configuring a kernel, you can try to optimize the kernel for your specific system.

One thing that you can do is use modules for some features, rather than building those features directly into the kernel. This is a relatively safe way to build options that you are unsure of whether or not you need. If you don’t need it, you don’t have to load the module into the kernel, but if you do need it, it is already built and ready to insert into the kernel (see “man insmod”).

Remember, the smaller the kernel, the more efficient the kernel will be. That being said, unless you know that you need an option to boot the machine, you should probably build as many options as you can as modules.

If you have questions regarding the configuration of the kernel, you can refer to the official Linux Kernel Howto which can be found here. You can also look for documentation on specific hardware in the /usr/src/linux/docs directory.

Once you have finished configuring your kernel, go ahead and save the configuration. You may even want to save the configuration file somewhere where you will be able to get at it easily (this is easy to do in both “make menuconfig” and “make xconfig”).

This can be a major time saver because you can load this file into both the “make menuconfig” and “make xconfig” kernel configuration menus. If you need to rebuild the kernel making only a few changes (i.e. you get an error or two while booting your new kernel…), you can load this file up and then make your changes.

After saving the configuration, you will need to run the following commands to compile the kernel.

make dep #make bzImage

If you have a multi-processor machine and are already booted to an SMP kernel (Symmetric Multi-Processing), you can try “make bzImage -j 2”. The “-j” switch tells “make” to use more threads, and as a consequence, more processors, if they are available. See “man make” for more information.

Depending on the speed of the machine that you are using to compile the kernel, you may have from a few minutes to several hours to wait. With most modern machines, this should not take more than 1/2 hour to complete, and chances are that it will go much faster. A typical 1 GHz machine with 256Mb RAM should finish in 5-10 minutes, depending on what you chose to compile.

You now have the kernel binary, bzImage. This binary can be found in /usr/src/linux/arch/i386/boot/. Go ahead and name it whatever you like, and then copy it to the /boot directory:

cd /usr/src/linux/i386/boot/ cp bzImage YourKernelName cp YourKernelName /boot/

Next, you will (optionally) build and install your modules, assuming that somewhere in your configuration you chose to build at least one option as a module.

make modules or, for SMP machines, #make modules -j 2

Once that has run its course, you will want to run:

make modules_install

This installs the modules in /lib/modules/X.Y.Z where X.Y.Z is the kernel version you are building.

Now you are ready to make your machine bootable to the new kernel. Be sure to back up your file, which is in the boot directory. You can then copy your new file from /usr/src/linux to the /boot directory.

cd /boot/ #mv #cd /usr/src/linux #cp /boot/

You are now ready to modify the /etc/lilo.conf file to get your new kernel to boot. I am assuming that you are using lilo, if you are using something else (such as GRUB), you will need to refer to that documentation for bootloader information.

All that you have to do is add an entry, similar to the following, to your lilo.conf. To do that, open /etc/lilo.conf in your favorite text editor (my favorites are Advanced Editor on the KDE desktop, and ‘pico’ from the command line). Add something like the following at the end of the file:

image=/boot/YourKernelName label=MyNewKernel read-only root=/dev/hda1

If you have other lines in the other entries in your lilo.conf file (such as ‘append=’), you may want to copy those lines as well. The line “root=/dev/hda1”, refers to the first partition of the first IDE drive. That line may be different depending on your configuration. You can safely copy the “root=” line from another entry (that boots!!) in the lilo.conf file.

That is it, run lilo:


and make sure that all of your entries are valid.

You are now ready to reboot your machine into the new kernel. If something goes wrong, you can remove the entry from lilo.conf, rename the /boot/ file back to, and rerun lilo. After that, try, try and try again!

Good luck!