Compiling the Linux Kernel

Quick Intro

It was my curiousity and interest that drove me to delve into the Linux Kernel. I am an amature programmer, went to school, and was certified as a Unix/Linux System Administrator. I had been told that the kernel was a program just like other programs, but I didn't really grasp that until I configured, compiled, and now run my personally compiled kernels. Compiling the kernel is not something most people will do, but succeeding at customizing your own kernel brings it's own gratification. I assume that you have some basic Unix/Linux knowledge going into this. This procedure is done mostly from the command line, and I don't stray onto other topics used in the compilation process. Compiling the kernel may seem intimidating, but the challenge is fun. I made these notes in the hope they will be helpful others.

Baby Steps

Start small. Diving in head over heals into the latest unstable kernel could give you a lashing you won't forget. I would recommend first recompiling the standard kernel that came with your distribution. It is solid, and is a good place to get your feet wet. I started with 2.4.21 that came with my Mandrake 9.1 install. You have to make sure the kernel source code is installed. With rpm based distros, it will be called something like kernel-source-2.X.X.rpm. It installs in /usr/src. When you have the sources installed go into the directory /usr/src/linux. You will notice in /usr/src/ that "linux" is actually a link to the root of the kernel sources directory. If you download the sources for another kernel later, just make the "linux" link in /usr/src/ point to the root directory of that kernel (ex: cd /usr/src; ln -s /path/to/new/kernel/2.6.0-test2 linux ). All of the commands discussed in this document are executed in /usr/src/linux unless otherwise noted. This document is based on my x86 experience so far with Linux.

The Process

Configuring the Kernel

There are 3 different kernel configuration programs which, in the end, do the same thing.
  • First up is "xconfig". This is run by typing ' make xconfig ' and is a friendly (as friendly as it gets, so far) interface for configuring the kernel. If you are new to configuring the kernel, use this program.
  • The second program is "menuconfig" which is run with ' make menuconfig '. It is not that bad a way to configure the kernel, but it is text based, so there is no mouse interaction. Try it sometime if you want to see it. Otherwise just use "xconfig".
  • The third way is not so fun. It is the origional "config". It is just a very long sequence of questions about how to configure the kernel. There is no way to go back to the previous question if you mess up, you just have to restart the configuration. I would recommend taking a look at it sometime after you have gotten used to compiling a kernel, but just for historical reference.
If you want to start a fresh compile, type ' make clean ' followed by ' make mrproper '. These two commands start you at ground zero.

After a fresh install of the kernel sources, go to the /usr/src/linux directory, and type ' make xconfig ' for the graphical kernel configuration program. With a stable kernel, the configuration is already good, so you can change a few things if you want, but be careful. If you aren't sure what some option means, take a look at it's explaination. I have not always found these explainations helpful, but they are worth a look if you have no clue. I wouldn't recommend making changes the first time, just to eliminate the chance of mis-configuring something. Save the configuration (with or without changes). A personal habit of mine is to keep a directory where I store kernel configurations, and I name them well so that if I change a configuration in a drastic way, I have a fallback configuration that I can start from, without starting completely fresh. An example name would be 2.6.0-test2_2.config. Then if I mess up when I am trying to compile my 2.6.0-test2_3.config kernel, I type ' make clean ', ' make mrproper ', ' cp /path/to/saved/configs/2.6.0-test2_2.config .config ' and start the configuring again. After configuring the kernel the way you want, save the file (File->Save or [ctrl]s ). Then exit the configuration program.

Compiling the Kernel

Kernels prior to 2.5 require the next command to be ' make dep ', while kernels 2.5 and later do not use this. Next step is typing ' make bzImage ' which makes the kernel image. It is normally run with nohup, as in ' nohup make bzImage & ' followed by ' tail -f nohup.out ' to follow the progress. The nohup runs the compliation so that it is unable to be interupted. If the compile ends in an error, read the error and see what you can gather from it. Googling for that error may present you with a message board dialog of others who have encountered the same problem. A clean compile of a stable kernel shouldn't end in errors though.

Compiling the Modules

Next, type ' make modules '. This is the longest process of compiling a new kernel. If you receive errors during the module compilation, trace back to the very first error message of the compile, and look to see what module had the error in it. If you don't need this module then start fresh, this time disabling that module. Some of the module names are hard to identify, but look closely at the names of the modules in "xconfig", or search Google to find what section of the kernel configuration the module is in. Recompile until all modules compile successfully. Don't worry about "warnings" you may see pass during compilation, the "errors" are the show stoppers.

Installing the Modules

Now comes the installation of the modules. This is done with ' make modules_install '. This is relatively quick. After this completes successfully, the Kernel and it's modules are DONE compiling :)

Ready the Kernel for Booting

This involves a few quick steps.

1. ' cp /usr/src/linux/arch/i386/boot/bzImage /boot/bzImage-some-descriptive-name '
    Copies kernel image to /boot directory where it is accessed for booting
    (ex: cp /usr/src/linux/arch/i386/boot/bzImage /boot/bzImage-2.6.0-test2_3 )
2. ' cp /usr/src/linux/.config /boot/config-same-descriptive-name '
    Copies a working configuration file to /boot, just for reference
    (ex: cp /usr/src/linux/.config /boot/config-2.6.0-test2_3 )
3. ' mkinitrd /boot/initrd-same-descriptive-name.img [EXTRAVERSION_name] '
    This is found as a directory in /lib/modules/. By the way, the
    EXTRAVERSION_name can be changed before compiling. Before the ' make bzImage ', edit
    the file "Makefile", and add your extraversion name to the EXTRAVERSION = "" line, and save.
    (ex: mkinitrd /boot/initrd-2.6.0-test2_3.img 2.6.0-test2 )
    *note* You may not need an initrd. This depends on whether you have all modules required for booting
    compiled into the kernel. If you compiled as a module a driver needed for booting (like a scsi drive/ide controller/etc)
    then make sure to generate this initrd so your kernel has access to the modules to boot itself
4. Edit the bootloader configuration file.
    In my case, I use LILO, so I edit /etc/lilo.conf. If you use GRUB or another bootloader,
    edit it's configuration file to allow the option of booting using your new kernel
    This is an entry I would make in my lilo.conf file for a new kernel:

    label="Kernel 2.6.0-test2_3"

You can model the entries already in your config file, such as the root=, and append=""
Leave your old kernel entry in here. Do not get rid of it until you know you won't ever need it again.
Save the file.
5. Run /sbin/lilo to complete kernel boot installation (This step only applies to LILO users)
6. Reboot, and select your new kernel with the bootloader

If your kernel does not boot successfully, I know it is a bit disappointing. Take written notes about any errors you see, and specific actions that do, or don't, happen. Reboot using your standard kernel, do some online research if necessary, and try, try again.

Quick Review of Steps

cd /usr/src/linux;
make clean;
make mrproper;
make xconfig;
[make dep];    (only for pre 2.5 kernels)
nohup make bzImage;
make modules;
make modules_install;
cp /usr/src/linux/arch/i386/boot/bzImage /boot/bzImage-with-descriptive-name;
cp /usr/src/linux/.config /boot/config-with-descriptive-name;
mkinitrd /boot/initrd-with-descriptive-name.img [EXTRAVERSION_name];
edit /etc/lilo.conf

After compiling a few kernels, you will develop your own command routine. Mine is:

cd /usr/src/linux; make clean; make mrproper; cp /path/to/saved/config .config; make xconfig;
make -j2 bzImage && make modules && make modules_install;

Depending on the speed of your computer, compile times (from when ' make bzImage ' starts, until ' make modules_install ' is done) can range from 10 mins to 20 hrs. My 1.2GHz Athlon takes 25 mins, my 450MHz PIII takes 2 hrs, and my oooold 486 66MHz takes just over 20 hrs.

I aspire to one day make significant contributions to the Linux kernel, and to the Open Source community in general. This tutorial, and my website are my humble start :)

If you have read this far, thank you for sticking with me, and I hope I helped you gain a more intimate understanding of the Linux kernel. I can be reached with questions at my email address:

daniel <at> alien2thisworld <.dot> net