Building a Linux Kernel

Alexey Eremenko "Technologov"

$Revision: 01 $

$Date: 2007-05-06 $

Revision History
Revision 118 May 2007A.E.
First public release

Scenarios

Usually, there is no need to upgrade or rebuild your kernel. Similarly, usually there is no need to upgrade your computer's BIOS. Just like with a BIOS, I would not recommend building your Linux kernel unless you have a good reason to.

Here, I will give you a few valid reasons, why rebuilding a kernel might be needed in your particular situation.

  • Hardware: Some hardware may be not supported by your current kernel, or worse yet, unstable support.

    For example my VIA 1617A audio codec failed every day on standard openSUSE 10.2 kernel in such a way, that only full system shutdown helped (init 0), or restart into a good kernel. First, I digged into the audio/ALSA driver problem, but it turned out to be a core PCI problem. So a simple upgrade to 2.6.20.7 saved me.

    In extreme cases, you may not be able to use this-or-that Linux ditribution, and openSUSE is no exception. If this happens, I have two recommendations: first is to install an older version of openSUSE, then upgrade all the packages to the latest stable version, except the kernel, and second recommendation is to participate in community open BETA testing. I usually take the second way, and it already saved me once. If you're a paying customer, your support company should solve this problem for you.

  • Security: there are some kernel modules that you may want to get rid of. For high-security systems, you could build-in everything what's needed, and disable loadable kernel modules (LKMs). This can be a good thing for an embedded system, but a very bad thing for a desktop.

    There may be additional modules that increase overall system security, such as: AppArmor.

  • Education: learning and experimenting is very important to become knowledgeble user.

  • Features: some programs require kernel drivers, and while most of them are capable of build-install-and-run a driver on the go, in some specific cases full kernel rebuild might be required. few years ago, the perfect feature that I wanted was: UnionFS, today it can be something more advanced, like: OpenVZ or advanced iptables/netfilter modules.

General information: There are several kinds of Linux kernels: SUSE-kernels, that have extra functionality, such as AppArmor, Linus Torvalds' kernels (also known as Vanilla kernels) - those are the official Linux kernels, and highly experimental Andrew Morton (-mm) kernels.

There were 6 generations of Linux kernels:

  • prehistoric: 0.01. Year: 1991.

  • first: 1.0 series. Year: 1994.

  • second: 1.2 series. Year: 1995.

  • third: 2.0 series. Year: 1996.

  • fourth: 2.2 series. Year: 1999.

  • fifth: 2.4 series. Year: 2001.

  • sixth: 2.6 series. Year: 2004.

Today, we are using 6th generation Linux kernels almost exclusively, that is: 2.6 kernel series.

Today's vanilla (Linus') kernels have a long version: 2.6.x.y, where x is the so called SUBLEVEL, which in reality translates into extra features, while y is the EXTRAVERSION, which in reality translates into extra stability.

Today's SUSE kernels have even longer name: for example openSUSE 10.2 has: 2.6.18.2-34-default so the -34 means a build number within SUSE tree and “default” means that it is optimized for normal desktop machines. Server machines may have something else.

There were kernels with second number odd, such as: 1.3, 2.1, 2.3, 2.5 and those kernels were experimental (unstable).

It is unlikely that we will reach next-generation of kernels anytime soon, because the open-source community has decided that the architecture of 2.6 is good, and from now we will evolve, rather than revolve.

General recommendation: Do not disable any modules that you are unsure about them and their place in the Linux operating system ! For example your desktop system might not even have a SCSI devices, but in Linux, the SCSI driver subsystem is used for _every_ disk out there, including IDE/SATA/SCSI/Firewire/USB/you-name-it... so if you disable that one, you will end up with a non-working kernel, so watch out!

In the general rule of thumb, it's best to base your new kernel configuration upon an already existing and running kernel. To do that, just do: > make oldconfig

Procedure to download a vanilla kernel

  1. Go to: http://www.kernel.org

  2. There is a line named: “The latest stable version of the Linux kernel is: ” If you press on the number that follows it, you will download *only* the patch vs. previous kernel. Since we are not kernel developers, we probably want a full kernel, so we press at the “F” button on the same line.

    I would recommend creating a ~/Linstall folder and drop the kernel there.

    Alternatively you could look at the FTP repository for older kernels, in case you want to degrade to an older one.

  3. To uncompress the archive, just do:

    tux@opensuse:~/Linstall> tar xvf linux-2.6.20.7.tar.bz2

Procedure to patch a kernel

  • Enter the directory.

    tux@opensuse:~/Linstall> cd linux-2.6.20.7/

    If your patch is plain text, just do:

    tux@opensuse:~/Linstall/linux-2.6.20.7> cat yourpatch.diff | patch -p1

    If your patch is a .bz2 compressed text, then do:

    tux@opensuse:~/Linstall/linux-2.6.20.7> bzcat yourpatch.diff | patch -p1

    If your patch is a .gz compressed text, then do:

    tux@opensuse:~/Linstall/linux-2.6.20.7> gzip -dc yourpatch.diff | patch -p1

    Patches can also be applied in reverse with -R parameter.

    tux@opensuse:~/Linstall/linux-2.6.20.7> cat yourpatch.diff | patch -p1 -R

    To test patches without really applying them:

    tux@opensuse:~/Linstall/linux-2.6.20.7> cat yourpatch.diff | patch -p1 --dry-run

Procedure to configure a kernel

After the patches have been applied, it is time for configuration.

  1. The first step is just changing the version number, not configuring itself.

    Use your favourite editor to edit Makefile.

    The first 4 lines, that you will see are those:

    VERSION = 2
    PATCHLEVEL = 6
    SUBLEVEL = 20
    EXTRAVERSION = .7
    

    You can change the last line from .7 to something like “.7-mykernel

  2. Reuse your current configurtaion:

    Now you can just start from your current config file, and just transfer it to the new kernel.

    The safest way to transfer old config to new kernel, is to use: “make oldconfig”. This command is safe because it asks you for changes if there are any new options in the kernel config.

    Another option is to copy your current config from /boot/config-2.6.x to ./.config, but since this copy doesn't check for any changes, there is a risk of consistency problems.

  3. Now, the Real configuration begins - it consists of hundreds of options.

    The options, that are available to you are:

    make config - Uses very primitive command-line configurator. That's a DoS attack against admins - not recommended :) More Seriously: This method should only be used if you remote-access your Linux box from a terminal that does not support neither GUI nor ncurses. Windows telnet is one such example.

    make menuconfig - Uses ncurses for configuration dialog. Uses tex-mode (console) but with menus. Make sure you install “ncurses-devel” package first.

    make gconfig - Uses Gtk for configuration dialog.

    make xconfig - Uses Qt for configuration dialog. I recommend this one.

  4. As there are too many options available, most people only know what's relevant to them.

    And I hope you remember my recommendation from beginning of this guide: Do *not* touch configuration settings if you unsure how they relate to the rest of the operating-system, or you might end up with a non-working kernel ! BEWARE !

The Final Construcion...

  1. That one is simple. The procedure is outlined below:

    # make clean
    # make all
    # make modules_install install
    

    Finally, this will build and install both the Linux kernel and it's modules into /boot directory. Make sure your bootloader knows about the new kernel. For GRUB look at /boot/grub/menu.lst and add your newly compiled kernel manually, based on the entry that already exists.

    You should add something like this to the end of your GRUB config:

    title 2.6.20.7-mykernel
    root (hd0,2)
    kernel /boot/vmlinuz-2.6.20.7-mykernel root=/dev/hdd3 vga=0x317 resume=/dev/hdd8 splash=0 showopts
    initrd /boot/initrd-2.6.20.7-mykernel
    

    The /dev/... and root () parameters should match your default kernel.

  2. Restart your system now and you're Done !

For More Information

The official Linux kernel website: http://www.kernel.org

An excellent book from Mandrake covering Building the Linux kernel: http://www.mandriva.com/en/community/resources/documentation