Building a Linux kernel
Because Linux is evolving so rapidly, it is much more likely that you'll be faced with the need to build a Linux kernel than you would if you were running a big-iron operating system. Kernel patches, device drivers, and new functionality are constantly becoming available. This is really something of a mixed blessing. On one hand, it's convenient to always have support for the "latest and greatest," but on the other hand it can become quite time consuming to keep up with the constant flow of new material. But after you successfully build a kernel once, you'll feel empowered and eager to do it again.
It's less likely that you'll need to build a kernel on your own if you're running a "stable" version. Linux has adopted a versioning scheme in which the second part of the version number indicates whether the kernel is stable (even numbers) or in development (odd numbers). For example, kernel version 2.4.3 would be a "stable" kernel, whereas 2.5.3 would be a "development" kernel. Now you know.
Linux kernel configuration has come a long way, but it still feels very primitive compared to the procedures used on some other systems. The process revolves around the .config file in the root of the kernel source directory (usually /usr/src/linux).4 All of the kernel configuration information is specified in this file, but its format is somewhat cryptic. Use the decoding guide in Documentation/Configure.help to find out what the various options mean.
To save folks from having to edit the .config file directly, Linux has several make targets that let you configure the kernel with different interfaces. If you are running X Windows, the prettiest configuration interface is provided by make xconfig. This command brings up a graphical configuration screen on which you can pick the devices to add to your kernel (or compile as loadable modules).
If you are not running X, you can use a curses-based5 alternative invoked with make menuconfig. Finally, there is the older style make config, which prompts you to respond to every single configuration option available without letting you later go back and change your mind.
We recommend make xconfig if you are running X and make menuconfig if you aren't. Avoid make config.
These tools are straightforward as far as the options you can turn on, but unfortunately they are painful to use if you want to maintain several versions of the kernel for multiple architectures or hardware configurations.
The various configuration interfaces described above all generate a .config file that looks something like this:
# Automatically generated make config: don't edit # # Code maturity level options CONFIG_EXPERIMENTAL=y # # Processor type and features # # CONFIG_M386 is not set # CONFIG_M486 is not set # CONFIG_M586 is not set # CONFIG_M586TSC is not set CONFIG_M686=y CONFIG_X86_WP_WORKS_OK=y CONFIG_X86_INVLPG=y CONFIG_X86_BSWAP=y CONFIG_X86_POPAD_OK=y CONFIG_X86_TSC=y CONFIG_X86_GOOD_APIC=y ...
As you can see, the contents are rather cryptic and provide no descriptions of what the CONFIG tags mean. Sometimes you can figure out the meaning. Basically, each CONFIG line refers to a specific kernel configuration option. The value y compiles the option into the kernel; m enables it, but as a loadable module.
Some things can be configured as modules and some can't. You just have to know which is which; it's not clear from the .config file. There is also no easy mapping of the CONFIG tags to meaningful information. However, you can usually extract this information from the Config.in file located in each driver directory. The Config.in files are difficult and inconvenient to track down, so it's best to just use make xconfig or make menuconfig.
Once you have a working, running kernel, you may need to pass special configuration options to it at boot time, such as the root device it should use or an instruction to probe for multiple Ethernet cards. The boot loader (typically LILO or GRUB) passes in these options. You add static configuration options to the /etc/lilo.conf or /boot/grub/grub.conf file, depending on which boot loader you use. See page 23 for more information.
If it's not possible to edit the boot loader configuration file (perhaps you broke something and the machine can't boot), you can pass the options in by hand. For example, at a LILO boot prompt you could type
LILO: linux root=/dev/hda1 ether=0,0,eth0 ether=0,0,eth1
to tell LILO to load the kernel specified by the "linux" tag, to use the root device /dev/hda1, and to probe for two Ethernet cards.
A similar example using GRUB would look like this:
grub> kernel /vmlinuz root=/dev/hda1 ether=0,0,eth0 ether=0,0,eth1 grub> boot
Building the Linux kernel binary
Setting up an appropriate .config file is the most important part of the Linux kernel configuration process, but you must jump through several more hoops to turn that file into a finished kernel.
Here's an outline of the entire process:
cd to /usr/src/linux.
Run make xconfig or make menuconfig.
Run make dep.
Run make clean.
Run make bzImage.
Run make modules.
Run make modules_install.
Copy /usr/src/linux/arch/i386/boot/bzImage to /boot/vmlinuz.
Copy /usr/src/linux/arch/i386/boot/System.map to /boot/System.map.
Edit /etc/lilo.conf (LILO) or /boot/grub/grub.conf (GRUB) to add a configuration line for the new kernel.
If you're using LILO, run /sbin/lilo to install the reconfigured boot loader.
The make clean step is not always strictly necessary, but it is generally a good idea to start with a clean build environment. In practice, many problems can be traced back to skipping this step.