How to Build a Linux Kernel
What The Kernel Does
The kernel is the heart of an operating system. It serves as an interface between the computer hardware and programs. It allocates resources such as disk space, memory, and CPU time. On multi-user platforms it controls what resources each user can access.In Linux, the command line interpreter and graphical user interface are not part of the kernel. They are applications like any other program that runs on the computer. This allows a great deal of flexibility since these programs can be written to provide any look and feel desired.
Why Build A Custom Kernel
Since the kernel interfaces with the hardware, it must have device drivers for every piece of hardware that it will need to be able to interface with. Linux distributions include kernels with a large number of device drivers configured in so they can work sub-optimally with most machine configurations out of the box.The distribution kernel will not be optimized for your particular CPU and hardware configuration. As a result it will be larger and slower than a kernel customized for your machine and it may not be able to take advantage of special features such as graphics acceleration that may be present in your graphics card.
Lastly, the Linux kernel is being continuously upgraded. Bugs are squashed, operations are made more efficient, support for new devices and protocols are added. For all of these reasons you will want to upgrade to the current stable release.
Preparation
The first thing you need is to build a list of the hardware you need to support on your machine. You will want to be sure to include drivers for all of your hardware and avoid including drivers for hardware you don't have and are unlikely to install. Unnecessary drivers make the kernel use more memory and run slower. With PC hardware drivers for non-existing devices will sometimes have conflicts with drivers for existing devices and interfere with their operation.The other thing you will need to know is which services you will need. Do you need the capability to connect to the Internet?
Getting The Kernel Sourece
The kernel source generally resides in /usr/src/linux-x.x.x or with the newer 2.6 kernels, linux-2.6.x.x (an extra digit in the version number) and you will need a symlink from /usr/src/linux to /usr/src/linux-x.x.x (whatever current version you are running).This is necessary because part of the files in /usr/include exist in the kernel source directory under /usr/src/linux/include and if you do not have the symlink in place the compiler will not be able to find these includes when building applications.
You will need to be logged in as root in order for the kernel source tree to have the correct permissions when you unpack it. In the following command examples, '#' is the command prompt, do not type this. Login as root, set umask to 022, and then cd to /usr/src.
# umask 022Linux kernels are distributed from ftp.kernel.org. Connect to this server with an ftp client of your choice.
# cd /usr/src
# ncftp ftp.kernel.orgThe various Linux kernel source packages are kept in various subdirectories of /pub/linux/kernel with directories for each major version from 1.0 all the way up to the current major version.
Login successful.
Logged in to ftp.kernel.org.
ncftp / >
Prior to version 2.6, development releases had odd major version numbers, 2.5, 2.3, 2.1, and stable releases had even numbers, 2.4, 2.2, and 2.0 for example. With 2.6 stable releases have been eliminated. Now every point release that includes security and bug fixes may also contain new features and new bugs. This is not a change I am happy about.
Once in ftp, change directories to the appropriate location.
ncftp / >cd /pub/linux/kernel/v2.6The ftp client ncftp defaults to binary transfer mode but if you use other ftp clients you may need to manually set the mode to binary before starting the transfer.
ncftp /pub/linux/kernel/v2.6 >
A dir or ls command will show the files in the subdirectory. There will exist both patches that can be applied to a current source tree to bring it up to the next version and full kernel distributions. The full distributions start with 'linux' and the patches start with 'patch'.
Linux distributions come with either a '.gz' extension which is a gzip'd tar archive or '.bz2' which are bzip'd with bzip2. The latter is smaller and preferable if you have bzip2 on your system. Once you decide which version you want use get filename to get the file.
Unpacking
Now that you have it in your directory, if you have the bzipped version unpack it with:# bunzip2 < linux-2.x.x(.x).bz2 | tar -xvf -If you have gzipped version unpack it with:
# gzcat linux-2.x.x(.x).gz | tar -xvf -Note that with versions up through 2.5 there are only three numbers in the version number but 2.6 added a forth number.
This will create a directory linux-2.x.x.(.x).
There will be a symlink from linux to the existing linux-2.x.x.(.x) source tree. You will need to remove that and put a symlink in place to the new source directory. If you do not do this it will use the incorrect include files to build kernel.
After deleting the old symlink and creating the new symlink, change directories to that directory.
# rm linuxAfter unpacking a distribution, the first thing you need to do after moving into the directory is to do a make mrproper.
# ln -s linux-2.x.x(.x) linux
# cd linux
# make mrproperWhat this step does is it sets up everything in the proper state for a build. It cleans up any temporary files left over from builds done by the development team and puts all the necessary symlinks in place.
Configuring A Kernel
Now you're ready to configure your kernel. You'll need a list of your hardware as mentioned earlier. There are three different interfaces available to configure your kernel.- # make config
Answer a long series of questions with no way to back up if you make a mistake. The only time you would want to use this interface is if you had a serious masochistic streak. - # make menuconfig
This is a nice curses driven text menu interface. It's nice and fast and easy. This is the one I use. - # make xconfig
This is an X-windows based GUI interface. It's slower than the text version and other than being prettier really has no advantages.
The make menuconfig will compile a small configure program and execute it. It will produce a menu that will be similar to this. The specific options will depend upon what kernel version you are using and what hardware platform. The following example is from a Sparc platform running Linux 2.2.26.
You can move up and down over these items with up and down arrow keys. At the bottom of the screen is <Select>, <Exit>, and <Help>. You can use the left and right arrows to move between these.
Code maturity level options --->
Loadable module support --->
General setup --->
Floppy, IDE, and other block devices --->
Networking options --->
Amateur radio support --->
SCSI support --->
Fiber Channel support --->
Network device support --->
Unix 98 PTY support --->
Video For Linux --->
XFree 86 DRI support --->
Filesystems --->
Watchdog --->
Kernel hacking --->
---
Load an Alternate Configuration File
Save to an Alternate Configuration File
If you have a question with respect to what a particular item does, highlight it with the up and down arrows, and then use the left and right arrows to choose <Help> then hit return. It will provide a brief explanation of what that item is for.
To exit a particular menu or sub-menu you the left and right arrows to select <Exit> and hit return and it will exit that menu back to the higher level or if you are at the higher level it will exit configure altogether.
Another resource you may find helpful in determining what to include what not is the Documentation directory. This directory contains text files describing various aspects of the Linux kernel.
Most drivers give you three options, you can say Y)es to include them, N)o to not include them or M)odule to make them loadable modules.
Once you've selected what you want to include, exit the top level menu. At that point it will ask if you want to save your new kernel configuration. Answer Y)es and then you are ready to build your new kernel.
Building A Linux Kernel
Now you have created a kernel configuration. If you have a multiple CPU machine, you may want to edit the Makefile to add -j N where N is the number of parallel jobs to run as one of the MAKE options. Generally, the ideal number of jobs to run is the number of CPU's plus one. The reason for the plus one is that otherwise at least one CPU will be stalled part of the time waiting on disk I/O. By adding one more job it ensures there is always at least one compile process waiting for CPU time while another is loading source from disk. After making that adjustment type the following to build a kernel.# make depWhen this completes you will either have a "bzImage" if a PC or a "vmlinux" if Sparc and a System.map file. The bzImage is a compressed kernel image that generally is used on PC's, the vmlinux file is an uncompressed kernel image used on Sparc. And the System.map file indicates where various things are located in kernel memory.
# make clean
# make bzImage (for PCs) or # make vmlinux (for Sparc)
Installing a New Kernel
The Linux kernel resides in the /boot directory along with the System.map file. Generally, it is advisable to have more than one kernel available to boot so that if a fatal bug exists in the most recent version you can fall back to an older version to boot the system and make any necessary changes.Generally, what I do is move the kernel to /boot/vmlinux-2.x.x (version) and the System.map to /boot/System.map-2.x.x (version), providing the version is different than the current kernel present. If not, then I would move the original to .old and then move the new kernels there.
Finally, I place a symlink from /boot/vmlinux-2.x.x. to /boot/vmlinux and from /boot/System.map-2.x.x to /boot/System.map.
If you are doing this on a PC, it will be bzImage-2.x.x instead of vmlinux-2.x.x but otherwise the same.
The reason the symlinks are necessary is that some utilities will need to read the linux kernel symbol table, and others will need to read the System.map file. Those applications don't know to search for different version names so you need to have the symlinks so that they can find it.
Generally, I like to keep about three kernels on a machine in case problems occur so I can fall back at least two versions if necessary.
The Linux boot loader needs to know where to find the kernel and which kernel is the default kernel. On a PC platform, the boot loader is called "lilo", on a Sparc platform it is called "silo". From the end users perspective they operate essentially the same.
This file allows you to declare multiple kernels and give each different labels that can be used during the boot process to select a particular kernel. Below is an example from a Sparc system running Linux 2.2.26.
The "st=64" option is something only necessary for systems which have SCSI host adapters and for which the default buffer size is inadequate.
You should keep at least two previous kernels in place and give them labels like "linux.old", "linux.oldest", so that if something goes wrong with your new kernel you can boot one of the old kernels.
A configuration file called /etc/lilo.conf (or /etc/silo.conf on Sparc) specifies the various kernel parameters.
timeout=50After you edit the configuration file you have to run lilo (on a PC) or silo (on a Sparc) to update the master boot record.
partition=1
root=/dev/sda1
default=vmlinux
image=/boot/vmlinux-2.2.26
label=vmlinux
root=/dev/sda1
read-only
append="st=64"
image=/boot/vmlinux-2.2.26.old
label=vmlinux.old
root=/dev/sda1
read-only
append="st=64"
image=/boot/vmlinux-2.2.25
label=vmlinux.older
root=/dev/sda1
read-only
append="st=64"
Once you've completed this, you're done, assuming the new kernel works properly.
Errors or Omissions
If you see any glaring errors or omissions, please e-mail nanook@eskimo.comThank you.


