Intro and Gathering Information
Part 2 - Preparing the Source Tree
Part 3 - Configuring the Kernel Source
Part 3 Continued - Configuring the Kernel
Part 4 - Building the Kernel
Part 5 - Installing the Kernel
Part 6 - Editing the Boot Loader Configuration
Reboot the Machine (and Enjoy)
Appendix A - Patching the Kernel Source
Appendix B - Building a 2.6 Kernel
Appendix C - Additional Notes as 2.6 Develops
Appendix D - Using the Initrd
Why?
The focus of this article, is to build a custom Linux kernel for your server or desktop machine. The kernel will be optimized for the machine's processor, and will contain support only for the drivers and features that are going to be needed. Another reason to compile a kernel is to add support for a feature that is missing from a vendor supplied kernel, or to get a piece of hardware working.
The end result will be a smaller, faster kernel with all the fixes and enhancements found in the latest stable version, without such complex workarounds like initial ramdrives (initrd) that allow modular support of critical drivers to support a wide variety of hardware configurations.
Me? Compile a kernel?
Yes, you. While the task may sound daunting, it's really not that difficult. First of all, if you know your machine and are familiar with Linux, the configuration will be intuitively easy for you. Even if you don't, we'll show you how to gather the required information.
It is reasonably safe to attempt this, provided we make correct configuration choices for critical chipset drivers. Data corruption hurts. Also, we always preserve the original vendor supplied kernel, module tree and boot loader entry, so that if we screw up or need to roll back to the original kernel for other reasons, it's a simple matter of restarting the machine and choosing the old kernel from the boot menu. If you are doing this remotely on a server, you will have to call someone to reboot the machine if you lose access. This is usually the worst that will happen, if careful.
Gathering Information
First of all, most of this procedure is going to be performed as a normal unpriviledged user of the system. It is not until we actually install the finished kernel that we need root priviledges. However, this user must have access to the system. A user jailed in his home directory (as is often the case for shell accounts provided with web hosting) will not do.
We are going to be typing commands in a terminal. This can be a tty login, or an xterm or similar GUI terminal program on your local machine or a remote shell login. (SSH... secure shell is preferred)
Let us assume that we're logging onto a machine we know absolutely nothing about. The first thing we'd like to know, is what Linux distribution is on the machine. There is usually a text file in the /etc directory that states the name and version of your distribution. It can be named release, issue, redhat-release, slackware-version... whatever. The /etc/issue file is normally what is used to display a welcome message, when you log on to the system. We then want to know the version of the running kernel.
You can see the commands I've typed at the $ prompt (bash shell):
We view the file /etc/issue and see that we're running Redhat Linux 7.2. The uname command, gives us the kernel revision. It's a stock, redhat supplied 2.4.18 uniprocessor kernel.
There is a wealth of information about the running kernel available by examining the boot messages. This information is conveniently collated in the output of the dmesg command.
This will give you an idea of the features in the running kernel, and the hardware that is initializing. For example, the IDE controller:
The first line of dmesg shows us the kernel version, the user and host it was compiled on, when it was compiled, the compiler used and the distribution it was compiled on. Curiously, this Redhat 7.2 server is running a kernel that was compiled on Redhat 7.3. That just means that someone has installed a newer binary kernel package. Several lines below that, we can see that this machine has 1 Gigabyte of RAM. (This means that we will be enabling HIGHMEM support in the kernel)
Examine the output of dmesg on your own machine. We'll take some of that into consideration, when we configure the new kernel build.
There is also a wealth of information to be gleaned by examining various files on the /proc pseudo filesystem. The /proc filesystem is basically provided by the kernel as an interface to various kernel data structures.
To find out detailed information about the machine's processor(s), we examine /proc/cpuinfo with the cat command.
We already knew this from dmesg but we can see, we're on a uniprocessor system (not a SMP rig with multiple processors) and we have an Intel Pentium4 processor running at approximately 2 GHz. We can also see the flags (e.g. instructions) that the processor supports.
Next, we need to know what chipset and PCI bus devices we have. For a simplified display, we can use the lspci command without switches.
Well, now we know that we have an Intel i845 chipset, with ICH2 IDE controllers and onboard AC'97 Audio and an Nvidia graphics controller.
If we want to view more details about the PCI bus hardware, we use lspci -v for a more verbose display.
If your running kernel was compiled with backwards compatible "legacy /proc/pci support" enabled, more detailed information is also available by viewing /proc/pci with the cat command.
Much of this information may not make sense, for example, just what the Hell is an Intel 82801BA/BAM/CA/CAM Ethernet Controller anyway? We can guess that it's an onboard device. Fortunately, we already know what it is from the output of dmesg:
We know that this onboard ethernet controller uses the Intel EtherExpress Pro driver.
OK, that is an Intel system. What kinds of differences might we see if it were an AMD system? Here's a couple of examples of things to take note of. First in this example, the output of lspci shows that we have a VIA chipset. If this were the machine we were working on, it would be important, while configuring the kernel.
Now, some relevant excerpts from the output of dmesg:
Note the difference in the IDE controller, compared with the Intel configuration above.
Now, back to the Intel Pentium 4 rig, the machine we're going to be working with. There are a few more things we need to look at, before we start working on the kernel sources.
We should see which kernel modules are loaded, in our running kernel. We do this using the lsmod command. Note that as a non-root user, you may have to type the full path to this and other programs in the /sbin directory as it's not always in a normal user's path.
There is nothing out of the ordinary, here. Note that some of these drivers aren't going to be modules. In order for our custom kernel to be able to boot without using an initrd, things like the EXT3 filesystem and disk controller drivers need to be included right in the kernel. We will be compiling our network adapter driver as a module, though, for example.
We need to see the layout of our filesystems, also. What kinds of partition devices and filesystem types are we using? We already have a good idea, based on what we saw with dmesg, but we can view the output of df (diskfree). The -h and -T switches are "human readable" and "show type" respectively.
This is a pretty straight forward setup. A small boot partition that contains the kernel and boot loader, and one large root partition on the first IDE hard disk, /dev/hda. There are no SCSI disk partitions, which would be named /dev/sda1, sda2, sdb1, and so on. The filesystem that is in use, is EXT3. The tmpfs mount, (/dev/shm filesystem) is sort of like a ramdisk, but it's more dynamic. No memory is really used, until something is copied there and it's freed when removed. It exists in the page cache or even in swap.
We must get a look at the /etc/fstab file. This is the "filesystem table" that the system init uses to mount your filesystems. There is something very important here that needs to be checked.
Note that the spacing in fstab is unimportant, as long as there is at least one whitespace or tab between arguments.
See the first two lines with the LABEL= statements? The Ext3 filesystem supports the concept of volume labels. By default on a Redhat system, the partitions are mounted according to labels. It makes it easier to switch drives around on controllers. There's some kernel patch in redhat kernels that makes this work. Guess what? If we build a standard kernel without support for this, the system init scripts will not be able to mount our filesystems during startup. There will be no startup.
Note: While it's true there was a patch to work around this, the magic that makes "mount by label" possible is done using an initrd. If you are going to be using an initrd with your custom kernel, you don't need to change this.
I therefore recommend that we use a text editor, to edit fstab, and use the real partition devices. It's not a big deal, for we know them from the output of df -hT. The / filesystem is mounted on /dev/hda2, and /boot is mounted on /dev/hda1.
So change the LABEL= statements, to look like this:
Use the real partition device names in fstab, for your system. You also must ensure that there isn't anything silly in your boot loader's configuration file like root="label=/" or the kernel won't even be able to mount the root filesystem, but we will cover that later in the article.
Be very careful editing configuration files like fstab. If you stuff them up, you may have to start the system with a rescue disk and fix them. It's generally a good idea to rename a backup copy of configuration files you edit. Easier to rename it back again than to try reconstructing what you hosed.
We should now have enough information to get started. The next task is to unpack the kernel source, and start reading a couple of documentation texts .
Intro and Gathering Information
Part 2 - Preparing the Source Tree
Part 3 - Configuring the Kernel Source
Part 3 Continued - Configuring the Kernel
Part 4 - Building the Kernel
Part 5 - Installing the Kernel
Part 6 - Editing the Boot Loader Configuration
Reboot the Machine (and Enjoy)
Appendix A - Patching the Kernel Source
Appendix B - Building a 2.6 Kernel
Appendix C - Additional Notes as 2.6 Develops
Appendix D - Using the Initrd
Bookmarks