Buy this Book
Print Book $34.99 PDF $24.99 Read it Now!
Print Book £24.99
Add to UK Cart
Reprint Licensing

Linux Kernel in a Nutshell
Linux Kernel in a Nutshell

By Greg Kroah-Hartman
Book Price: $34.99 USD
£24.99 GBP
PDF Price: $24.99

Cover | Table of Contents


Table of Contents

Chapter 1: Introduction
Despite its large code base (over 7 million lines of code), the Linux kernel is the most flexible operating system that has ever been created. It can be tuned for a wide range of different systems, running on everything from a radio-controlled model helicoptor, to a cellphone, to the majority of the largest supercomputers in the world. By customizing the kernel for your specific environment, it is possible to create something that is both smaller and faster than the kernel provided by most Linux distributions. This book will go into how to build and install a custom kernel, and provide some hints on how to enable specific options that you will probably wish to use for different situations.
No Linux distribution provides the exact kernel most of its users want. Modern distributions have gotten very accommodating, compiling in support for every known device, for sound, and even for power conservation. But you will likely have a need that's different from the majority of users (and every distribution has to try to meet the needs of the majority). You may just have different hardware. And when a new kernel comes out, you may want to start using it without waiting for a distribution to be built around it.
For a host of reasons, you will want during your Linux career to sometimes build a kernel, or to tweak the parameters of one you are running. This book gives you the information you need to understand the kernel from a user's point of view, and to make the most common changes.
There are also good reasons to take features out of the kernel, particularly if you are running it on an embedded system or one with a small form factor.
When tweaking, it's helpful to understand the internals of kernel behavior. These are beyond the scope of this book, except for brief summaries that appear with certain options. The bibliography includes references to other books and material that can give you more background.
Do not configure or build your kernel with superuser permissions enabled!
The previous warning is the most important thing to remember while working through the steps in this book. Everything in this book, from downloading the kernel source code, uncompressing it, configuring the kernel, and building it should be done as a normal user on the machine. Only the two or three commands it takes to install a new kernel should be done as the superuser (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using this book
Do not configure or build your kernel with superuser permissions enabled!
The previous warning is the most important thing to remember while working through the steps in this book. Everything in this book, from downloading the kernel source code, uncompressing it, configuring the kernel, and building it should be done as a normal user on the machine. Only the two or three commands it takes to install a new kernel should be done as the superuser (root).
There have been bugs in the kernel build process in the past, causing some special files in the /dev directory to be deleted if the user had superuser permissions while building the Linux kernel. There are also issues that can easily arise when uncompressing the Linux kernel with superuser rights, as some of the files in the kernel source package will not end up with the proper permissions and will cause build errors later.
The kernel source code should also never be placed in the /usr/src/linux/ directory, as that is the location of the kernel that the system libraries were built against, not your new custom kernel. Do not do any kernel development under the /usr/src/ directory tree at all, but only in a local user directory where nothing bad can happen to the system.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Requirements for building and using the kernel
This chapter describes the programs you need to configure a kernel, build it, and successfully boot it. It's a smart idea to consult the file Documentation/Changes to verify the specific version number you should have of each tool described in this chapter. This chapter was based on the 2.6.18 kernel, and describes the versions of tools that work with that kernel. If you are using a different kernel, please verify that you have the required versions as specified in this file, or things might not work properly and it can be very hard to determine what went wrong.
Most Linux distributions offer an installation option to install a range of Kernel Hacking packages. If your distribution offers this option, it is easiest to install this instead of trying to track down all of the individual programs that are needed for this task.
Only three packages that are needed in order to successfully build a kernel: a compiler, a linker, and a make utility. This section describes the contents of each package.
The Linux kernel is written in the C programming language, with a small amount of assembly language in some places. To build the kernel, the GCC C compiler must be used. Most Linux distributions have a package entitiled gcc that should be installed. If you wish to download the compiler and build it yourself, you can find it at http://gcc.gnu.org.
As of the 2.6.18 kernel release, the 3.2 version of GCC is the oldest that can properly build a working kernel. Be warned that getting the most recent GCC version is not always a good idea. Some of the newest GCC releases don't build the kernel properly, so unless you wish to help debug compiler bugs, it is not recommended that you try them out.
To determine which version of gcc you have on your system, run the following command:
$ gcc --version
               
The C compiler, gcc, does not do all of the compiling on its own. It needs an additional set of tools known as binutils to do the linking and assembling of source files. The binutils package also contains useful utilities that can manipulate object files in lots of useful ways, such as to view the contents of a library.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Tools to build the kernel
Most Linux distributions offer an installation option to install a range of Kernel Hacking packages. If your distribution offers this option, it is easiest to install this instead of trying to track down all of the individual programs that are needed for this task.
Only three packages that are needed in order to successfully build a kernel: a compiler, a linker, and a make utility. This section describes the contents of each package.
The Linux kernel is written in the C programming language, with a small amount of assembly language in some places. To build the kernel, the GCC C compiler must be used. Most Linux distributions have a package entitiled gcc that should be installed. If you wish to download the compiler and build it yourself, you can find it at http://gcc.gnu.org.
As of the 2.6.18 kernel release, the 3.2 version of GCC is the oldest that can properly build a working kernel. Be warned that getting the most recent GCC version is not always a good idea. Some of the newest GCC releases don't build the kernel properly, so unless you wish to help debug compiler bugs, it is not recommended that you try them out.
To determine which version of gcc you have on your system, run the following command:
$ gcc --version
               
The C compiler, gcc, does not do all of the compiling on its own. It needs an additional set of tools known as binutils to do the linking and assembling of source files. The binutils package also contains useful utilities that can manipulate object files in lots of useful ways, such as to view the contents of a library.
binutils can usually be found in a distribution package called (not surprisingly) binutils. If you wish to download and install the package yourself, you can find it at http://www.gnu.org/software/binutils.
As of the 2.6.18 kernel release, the 2.12 release of binutils is the oldest that can successfully link the kernel. To determine which version of binutils you have on your system, run the following command:
$ ld -v
               
make is a tool that walks the kernel source tree to determine which files need to be compiled, and then calls the compiler and other build tools to do the work in building the kernel. The kernel requires the GNU version of
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Tools to use the kernel
While the version of the kernel that is running does not usually affect any user application, there are a small number of program for which the kernel version is important. This section describes a number of tools that are probably already installed on your Linux system. If you upgrade your kernel to a version different from the one that came with your distribution, some of these packages may also need to be upgraded in order for the system to work properly.
The util-linux package is a collection of small utilities that do a wide range of different tasks. Most of these utilities handle the mounting and creation of disk partitions and manipulation of the hardware clock in the system.
If you wish to download and install the util-linux package yourself, you can find it at http://www.kernel.org/pub/linux/utils/util-linux.
As of the 2.6.18 kernel release, the 2.10o release of util-linux is the oldest that works properly . It is recommended that you install the latest version of this package, because new version support new features added to the kernel. Bind mounts are one example of an option in newer kernels, and a newer version of util-linux is needed in order to have them work properly.
To determine which version of the util-linux package you have on your system, run the following command:
$ fdformat --version
               
The module-init-tools package is needed if you wish to use Linux kernel modules. A kernel module is a loadable chunk of code that can be added to or removed from the kernel while the kernel is running. It is useful to compile device drivers as modules and then load only the ones that correspond to the hardware present in the system. All Linux distributions use modules in order to load only the needed drivers and options for the system based on the hardware present, instead of being forced to build all possible drivers and options in the kernel in one large chunk. By using modules, memory is saved by loading just the code that is needed to control the machine properly.
The kernel module loading process underwent a radical change in the 2.6 kernel release. The linker for the module (the code that resolves all symbols and figures out how to put the pieces together in memory) is now built into the kernel, which makes the userspace tools quite small. Older distributions have a package called
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Retrieving the kernel source
When you're building your own kernel, you want the latest stable release. Many distributions provide their own packages of kernel sources, but these are rarely the most cutting-enge, recent versions. The distribution packages have the advantage of being built to be compatible with the compiler and other tools provided by the distribution ( explains the importance of their being compatible) but they may not end up providing the functionality or performance you want. If you can create your own environment with the latest kernel, compiler, and other tools, you will be able to build exactly what you want. This chapter focuses on determining which kernel sources to download, and how to obtain them.
In the past, the Linux kernel was split into only two trees, the "development" branch and the "stable" branch. The development branch was denoted by an odd number for the second release number, while the stable branch used even numbers. So, as an example, the 2.5.25 release was a development kernel, while the 2.4.25 release is a stable release.
But after the 2.6 series was created, the kernel developers decided to abandon this method of having two separate trees, and declared that all 2.6 kernel releases would be considered "stable", no matter how quickly development was happening. The few months between the major 2.6 releases would allow kernel developers the time to add new features and then stabilize them in time for the next release. Combined with this, a "-stable" kernel branch has been created that releases bugfixes and security updates for the past kernel release, before the next major 2.6 release happens.
This is all best explained with some examples, illustrated in . The kernel team released the 2.6.17 kernel as a stable release. Then the developers started working on new features and started releasing the -rc versions as development kernels so that people could help test and debug the changes. After everyone agreed that the development release was stable enough, it was released as the 2.6.18 kernel. This whole cycle usually takes about two to three months, depending on a variety of factors.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What tree to use
In the past, the Linux kernel was split into only two trees, the "development" branch and the "stable" branch. The development branch was denoted by an odd number for the second release number, while the stable branch used even numbers. So, as an example, the 2.5.25 release was a development kernel, while the 2.4.25 release is a stable release.
But after the 2.6 series was created, the kernel developers decided to abandon this method of having two separate trees, and declared that all 2.6 kernel releases would be considered "stable", no matter how quickly development was happening. The few months between the major 2.6 releases would allow kernel developers the time to add new features and then stabilize them in time for the next release. Combined with this, a "-stable" kernel branch has been created that releases bugfixes and security updates for the past kernel release, before the next major 2.6 release happens.
This is all best explained with some examples, illustrated in . The kernel team released the 2.6.17 kernel as a stable release. Then the developers started working on new features and started releasing the -rc versions as development kernels so that people could help test and debug the changes. After everyone agreed that the development release was stable enough, it was released as the 2.6.18 kernel. This whole cycle usually takes about two to three months, depending on a variety of factors.
Figure : Kernel development release cycle
While the development of the new features was happening, the 2.6.17.1, 2.6.17.2, and other stable kernel versions were released, containing bug fixes and security updates.
If you wish to just use the latest kernel for your work, it is recommended that you use the stable kernel releases. If you wish to help the kernel developers test the features of the next kernel release and give them feedback, use the development kernel release. For the purpose of this chapter, we will assume that you are using a stable kernel release.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Where to find the kernel source
All of the source code for the Linux kernel can be found on one of the kernel.org sites, a worldwide network of servers that mirror the Linux source code, enabling everyone to find a local server close to him. This allows the main kernel servers to be responsive to the mirror sites, and lets users download the needed files as quickly as possible.
The main http://www.kernel.org. site shows all of the current kernel versions for the various different kernel trees, as shown in .
Figure : The main kernel.org web site
To download the latest stable kernel version, click on the F character on the line for the kernel version. This will download the full source tree. Or you can navigate to the proper subdirectory for all of the 2.6 kernel versions, http://www.us.kernel.org/pub/linux/kernel/v2.6/, shown in .
Figure : The 2.6 kernel source directory
It is also possible to download the kernel source from the command line, using the wget or curl utilities, both of which should come with your Linux distribution.
To download the 2.6.17.8 kernel version using wget, enter:
$ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.8.tar.gz
--17:44:55--  http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.8.tar.gz
           => `linux-2.6.17.8.tar.gz'
Resolving www.kernel.org... 204.152.191.5, 204.152.191.37
Connecting to www.kernel.org|204.152.191.5|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 51,707,742 (49M) [application/x-gzip]

100%[=============================================>] 51,707,742    35.25K/s    ETA 00:00

18:02:48 (47.12 KB/s) - `linux-2.6.17.8.tar.gz' saved [51707742/51707742]
To download it using curl:
$ curl http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.8.tar.gz -o linux-2.6.17.8.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 49.3M  100 49.3M    0     0  50298      0  0:17:08  0:17:08 --:--:--  100k
For a quick and easy way to determine the latest kernel versions, use the information available at
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What to do with the source
Now that you have downloaded the proper kernel source, where is it supposed to go? We suggest creating a local directory in your home directory called linux/ to hold all of the different kernel source files:
$ mkdir ~/linux
            
Now move the source code into this directory:
$ mv ~/linux-2.6.17.8.tar.gz ~/linux/
            
And go into the linux/ directory:
$ cd ~/linux
$ ls
linux-2.6.17.8.tar.gz
Now that the source code is in the proper directory, we need to uncompress the tree:
$ tar -xzvf linux-2.6.17.8.tar.gz
            
The screen will be filled with files that are uncompressed, and you will be left with the following in the linux/ directory:
$ ls
linux-2.6.17.8.tar.gz
linux-2.6.17.8/
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Configuring and Building
Now that you have downloaded the source for your selected kernel version and installed it into a local directory, it is time to build the code. The first step is to configure the kernel with the appropriate options; the kernel can then be compiled. Both tasks are done through the standard make utility.
The kernel configuration is kept in a file called .config in the top directory of the kernel source tree. If you have just expanded the kernel source code, there will be no .config file, so it needs to be created. It can be created from scratch, created by basing it on the "default configuration," taken from a running kernel version, or taken from a distribution kernel release. We will cover the first two methods here, and the last two methods in .
The most basic method of configuring a kernel is to use the make config method:
$ cd linux-2.6.17.10
$ make config
 make config
scripts/kconfig/conf arch/i386/Kconfig
*
* Linux Kernel Configuration
*
*
* Code maturity level options
*
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?] Y
*
* General setup
*
Local version - append to kernel release (LOCALVERSION) []  
Automatically append version information to the version string (LOCALVERSION_AUTO) [Y/n/?] Y
...
The kernel configuration program will step through every configuration option and ask you if you wish to enable this option or not. Typically, your choices for each option are shown in the format [Y/m/n/?] The capitalized letter is the default, and can be selected by just pressing the Enter key. The four choices are:
y
Build directly into the kernel.
n
Leave entirely out of the kernel.
m
Build as a module, to be loaded if needed.
?
Print a brief descriptive message and repeat the prompt.
The kernel contains almost two thousand different configuration options, so being asked for every individual one will take a very long time. Luckily, there is an easier way to configure a kernel: base the configuration on a pre-built configuration.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating a configuration
The kernel configuration is kept in a file called .config in the top directory of the kernel source tree. If you have just expanded the kernel source code, there will be no .config file, so it needs to be created. It can be created from scratch, created by basing it on the "default configuration," taken from a running kernel version, or taken from a distribution kernel release. We will cover the first two methods here, and the last two methods in .
The most basic method of configuring a kernel is to use the make config method:
$ cd linux-2.6.17.10
$ make config
 make config
scripts/kconfig/conf arch/i386/Kconfig
*
* Linux Kernel Configuration
*
*
* Code maturity level options
*
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?] Y
*
* General setup
*
Local version - append to kernel release (LOCALVERSION) []  
Automatically append version information to the version string (LOCALVERSION_AUTO) [Y/n/?] Y
...
The kernel configuration program will step through every configuration option and ask you if you wish to enable this option or not. Typically, your choices for each option are shown in the format [Y/m/n/?] The capitalized letter is the default, and can be selected by just pressing the Enter key. The four choices are:
y
Build directly into the kernel.
n
Leave entirely out of the kernel.
m
Build as a module, to be loaded if needed.
?
Print a brief descriptive message and repeat the prompt.
The kernel contains almost two thousand different configuration options, so being asked for every individual one will take a very long time. Luckily, there is an easier way to configure a kernel: base the configuration on a pre-built configuration.
Every kernel version comes with a "default" kernel configuration. This configuration is loosely based on the defaults that the kernel maintainer of that architecture feels are the best options to be used. In some cases, it is merely the configuration that is used by the kernel maintainer himself for his personal machines. This is true for the i386 architecture, where the default kernel configuration matches closely what Linus Torvalds uses for his main development machine.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Modifying the configuration
Now that we have a basic configuration file created, it should be modified to support the hardware you have present in the system. For details on how to find out which configuration options you need to select to achieve this, please see . Here we will show you how to select the options you wish to change.
There are three different interactive kernel configuration tools: a terminal-based one called menuconfig, a GTK+-based graphical one called gconfig, and a QT-based graphical one called xconfig.
The menuconfig way of configuring a kernel is a console-based program that offers a way to move around the kernel configuration using the arrow keys on the keyboard. To start up this configuration mode, enter:
$ make menuconfig
               
You will be shown a screen much like .
The instructions for navigating through the program, and the meanings of the different characters, are shown at the top of the screen. The rest of the screen containing the different kernel configuration options.
The kernel configuration is divided up into sections. Each section contains options that correspond to a specific topic. Within those sections can be sub-sections for various specialized topics. As an example, all kernel device drivers can be found under the main menu option Device Drivers. To enter that menu, move the arrow key down nine times until the line Device Drivers ---> is highlighted, as shown in . Then press the Enter key. It will move you into the Device Drivers submenu and show it as illustrated in .
You can continue to move down through the menu hierarchy the same way. To see the Generic Driver Options submenu, press Enter again, and you will see the three options shown in . The first two options have a [*] mark by them. That means that this option is selected (by virtue of the * being in the middle of the [ ] characters), and that this option is a yes-or-no option. The third option has a
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building the kernel
Now that you have created a kernel configuration that you wish to use, you need to build the kernel. This is as simple as entering a one-word command:
$ make
  CHK     include/linux/version.h
  UPD     include/linux/version.h
  SYMLINK include/asm -> include/asm-i386
  SPLIT   include/linux/autoconf.h -> include/config/*
  CC      arch/i386/kernel/asm-offsets.s
  GEN     include/asm-i386/asm-offsets.h
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  MKELF   scripts/mod/elfconfig.h
  HOSTCC  scripts/mod/file2alias.o
  HOSTCC  scripts/mod/modpost.o
  HOSTCC  scripts/mod/sumversion.o
  HOSTLD  scripts/mod/modpost
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/conmakehash
  HOSTCC  scripts/bin2c
  CC      init/main.o
  CHK     include/linux/compile.h
  UPD     include/linux/compile.h
  CC      init/version.o
  CC      init/do_mounts.o
...
Running make will cause the kernel build system to use the configuration you have selected to build a kernel and all modules needed to support that configuration. While the kernel is building, make will display the individual file names of what is currently happening, along with any build warnings or errors.
If the kernel build finished without any errors, you have successfully created a kernel image. However, it needs to be installed properly before you try to boot from it. See for how to do this.
It is very unusual to get any build errors when building a released kernel version. If you do, please report them to the Linux kernel developers so they can be fixed.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Advanced building options
The kernel build system allows you to do many more things than just build the full kernel and modules. includes the full list of options that the kernel build system provides. In this section, we will discuss some of these advanced build options. To see a full description of how to use other advanced build options, refer to the in-kernel documentation on the build system, which can be found in the Documentation/kbuild/ directory of the sources.
The kernel build system works very well as a task that can be split up into little pieces and given to different processors. By doing this, you can use the full power of a multiprocessor machine and reduce the kernel build time considerably.
To build the kernel in a multithreaded way, use the -j option to the make program. It is best to give a number to the -j option that corresponds to twice the number of processors in the system. So, for a machine with 2 processors present, use:
$ make -j4
               
and for a machine with four processors, use:
$ make -j8
               
If you do not pass a numerical value to the -j option
$ make -j
               
the build system will create a new thread for every subdirectory in the kernel tree, which can easily cause your machine to become unresponsive and take a much longer time to complete the build. Because of this, it is recommended that you always pass a number to the -j option.
When doing kernel development, sometimes you wish to build only a specific subdirectory or a single file within the whole kernel tree. The kernel build system allows you to easily do this. To selectively build a specific directory, specify it on the build command line. For example, to build the files in the drivers/usb/serial directory, enter:
$ make drivers/usb/serial
               
Using this syntax, however, will not build the final module images in that directory. To do that, you can use the M= argument:
$ make M=drivers/usb/serial
               
which will build all the needed files in that directory and link the final module images.
When you build a single directory in one of the ways shown, the final kernel image is not relinked together. Therefore, any changes that were made to the subdirectories will not affect the final kernel image, which is probably not what you desire. Execute a final:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 5: Installing and Booting From a Kernel
Previous chapters showed you how to download and build your kernel. Now that you have an executable file -- along with any modules you built -- it is time to install the kernel and attempt to boot it. In this chapter, unlike earlier ones, all of the commands need to be run as the root user. This can be done by prefixing each command with sudo, by using the su command to become root, or actually by logging in as root.
To see if you have sudo installed and the proper access set up, do the following:
$ sudo ls ~/linux/linux-2.6.17.11/Makefile
Password:
Makefile
Enter either your own password at the password prompt, or the password of the system administrator (root). The choice depends on how the sudo command is set up. If this is successful, and you see the line containing:
Makefile
then you can skip to the next section.
If sudo is not installed or giving you the proper rights, then try using the su command:
$ su
Password:
# exit
exit
$
At the password prompt, enter the password of the system administrator (root). When the su program successfully accepts the password, you are transferred to running everything with full root privileges. Be very careful while as root, and do only the minimum needed; then exit the program to continue back as your normal user account.
Almost all distributions come with a script called installkernel that can be used by the kernel build system to automatically install a built kernel into the proper location and modify the bootloader so that nothing extra needs to be done by the developer.
Distributions that offer installkernel usually put it in a package called mkinitrd, so try install that package if you cannot find the script on your machine.
If you have built any modules and want to use use this method to install a kernel, first enter:
# make modules_install
            
This will install all the modules that you have built and place them in the proper location in the filesystem for the new kernel to properly find. Modules are placed in the /lib/modules/ KERNEL_VERSION directory, where
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using a Distribution's Installation Scripts
Almost all distributions come with a script called installkernel that can be used by the kernel build system to automatically install a built kernel into the proper location and modify the bootloader so that nothing extra needs to be done by the developer.
Distributions that offer installkernel usually put it in a package called mkinitrd, so try install that package if you cannot find the script on your machine.
If you have built any modules and want to use use this method to install a kernel, first enter:
# make modules_install
            
This will install all the modules that you have built and place them in the proper location in the filesystem for the new kernel to properly find. Modules are placed in the /lib/modules/ KERNEL_VERSION directory, where KERNEL_VERSION is the kernel version of the new kernel you have just built.
After the modules have been successfully installed, the main kernel image must be installed:
# make install
            
This will kick off the following process:
  • The kernel build system will verify that the kernel has been successfully built properly.
  • The build system will install the static kernel portion into the /boot directory and name this executable file based on the kernel version of the built kernel.
  • Any needed initial ramdisk images will be automatically created, using the modules that have just been installed during the modules_install phase.
  • The bootloader program will be properly notified that a new kernel is present, and it will be added to the appropriate menu so the user can select it the next the machine is booted.
After this is finished, the kernel is successfully installed, and you can safely reboot and try out your new kernel image. Note that this installation does not overwrite any older kernel images, so if there is a problem with your new kernel image, the old kernel can be selected at boot time.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Installing By Hand
If your distributtion does not have a installkernel command, or you wish to just do the work by hand to understand the steps involved, here are the steps involved.
  1. The modules must be installed:
    # make modules_install
                      
  2. The static kernel image must be copied into the /boot directory. For an i386-based kernel, do the following:
    # make kernelversion
    2.6.17.11
    
    Note that the kernel version will probably be different for your kernel. Use this value in place of the text KERNEL_VERSION in all of the following steps:
    # cp arch/i386/boot/bzImage /boot/bzImage-KERNEL_VERSION
                         
    # cp System.map /boot/System.map-KERNEL_VERSION
                         
                      
  3. Modify the bootloader so it knows about the new kernel. This involves editing a configuration file for the bootloader you use, and is covered later in for the GRUB and LILO bootloaders.
If the boot process does not work properly, it's usually because an initial ramdisk image is needed. To create this properly, use the steps in the beginning of this chapter for installing a kernel automatically, because the distribution install scripts know how to properly create the ramdisk using the needed scripts and tools. Because each distribution does this differently, it is beyond the scope of this book to cover all of the different methods of building the ramdisk image.
Here is a handy script that can be used to install the kernel automatically instead of having to type the previous commands all the time:
#!/bin/sh
#
# installs a kernel
#
make modules_install

# find out what kernel version this is
for TAG in VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION ; do
    eval `sed -ne "/^$TAG/s/ //gp" Makefile`
done
SRC_RELEASE=$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION

# figure out the architecture
ARCH=`grep "CONFIG_ARCH " include/linux/autoconf.h | cut -f 2 -d "\""`

# copy the kernel image
cp arch/$ARCH/boot/bzImage /boot/bzImage-"$SRC_RELEASE"

# copy the System.map file
cp System.map /boot/System.map-"$SRC_RELEASE"

echo "Installed $SRC_RELEASE for $ARCH"
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Modifying the Bootloader For the New Kernel
There are two common Linux kernel bootloaders: GRUB and LILO. GRUB is the one more commonly used in modern distributions, and does some things a little more easily than LILO, but LILO is still seen as well. We'll cover both in this section.
To determine which bootloader your system uses, look in the /boot/ directory. If there is a grub subdirectory:
$ ls -F /boot | grep grub
grub/
then you are using the GRUB program to boot with. If this directory is not present, look for the presence of the /etc/lilo.conf file:
$ ls /etc/lilo.conf
/etc/lilo.conf
If this is present, you are using the LILO program to boot with.
The steps involved in adding a new kernel to each of these programs are different, so follow only the section that corrisponds to the program you are using.
To let GRUB know that a new kernel is present, all you need to do is modify the /boot/grub/menu.lst file. For full details on the structure of this file, and all of the different options available, please see the GRUB info pages:
$ info grub
               
The easiest way to add a new kernel entry to the /boot/grub/menu.lst file is to copy an existing entry. For example, consider the following menu.lst file from a Gentoo system:
timeout 300
default 0

splashimage=(hd0,0)/grub/splash.xpm.gz

title 2.6.16.11
	root (hd0,0)
	kernel /bzImage-2.6.16.11 root=/dev/sda2 vga=0x0305

title 2.6.16
	root (hd0,0)
	kernel /bzImage-2.6.16 root=/dev/sda2 vga=0x0305
The line starting with the word title defines a new kernel entry, so this file contains two entries. Simply copy the lines from one instance of the title word to the next one, such as :
title 2.6.16.11
	root (hd0,0)
	kernel /bzImage-2.6.16.11 root=/dev/sda2 vga=0x0305
to the end of the file, and edit the version number to contain the version number of the new kernel you just installed. The title does not matter, so long as it is unique, but it is displayed in the boot menu, so you should make it something meaningful. In our example, we installed the 2.6.17.11 kernel, so the final copy of the file looks like:
timeout 300
default 0

splashimage=(hd0,0)/grub/splash.xpm.gz

title 2.6.16.11
	root (hd0,0)
	kernel /bzImage-2.6.16.11 root=/dev/sda2 vga=0x0305

title 2.6.16
	root (hd0,0)
	kernel /bzImage-2.6.16 root=/dev/sda2 vga=0x0305

title 2.6.17.11
	root (hd0,0)
	kernel /bzImage-2.6.17.11 root=/dev/sda2 vga=0x0305
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 6: Upgrading a kernel
Inevitably it happens, you have a custom built kernel, working just wonderfully except for one little thing that you know is fixed in the latest release from the kernel developers. Or a security problem is found, and a new stable kernel release is made public. Either way, you are faced with the issue of upgrading the kernel and you do not want to lose all the time and effort that went into making that perfect kernel configuration.
This chapter is going to show how easy it is to update a kernel from an older versions, while still retaining all of the configuration options from the previous one.
First off, please back up the .config file in the kernel source directory. You have spent some time and effort into creating it, and it should be saved in case something goes wrong when trying to upgrade.
$ cd ~/linux/linux-2.6.17.11
$ cp .config ../good_config
         
There are only five simple steps that are needed to upgrade a kernel from a previously built one:
  1. Get the new source code.
  2. Apply the changes to the old source tree to bring it up to the newer level.
  3. Reconfigure the kernel based on the previous kernel configuration.
  4. Build the new kernel.
  5. Install the new kernel.
The last two steps work the same as described before, so we will only discuss the first three steps in this chapter.
In this chapter, we are going to assume that you have built a successful 2.6.17.9 kernel release, and want to upgrade to the 2.6.17.11 release.
The Linux kernel developers realize that all users do not wish to download the entire source code to the kernel for every update. That would be a waste of bandwidth and time. Because of this, they offer a patch that can upgrade an older kernel release, to a newer one.
On the main kernel.org website, you will remember that it contained a list of the current kernel versions that are available for download:
Figure : The main kernel.org web site
Previously, you used the link pointed to you by the F to download the entire source code for the kernel. However, if you click on the name of the kernel release, it will download a patch file instead:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Download the new source
The Linux kernel developers realize that all users do not wish to download the entire source code to the kernel for every update. That would be a waste of bandwidth and time. Because of this, they offer a patch that can upgrade an older kernel release, to a newer one.
On the main kernel.org website, you will remember that it contained a list of the current kernel versions that are available for download:
Figure : The main kernel.org web site
Previously, you used the link pointed to you by the F to download the entire source code for the kernel. However, if you click on the name of the kernel release, it will download a patch file instead:
Figure : Downloading a patch from kernel.org
This is what we want to do when upgrading. But we need to figure out what patch to download.
A kernel patch file only will upgrade the source code from one specific release to another specific release. Here is how the different patch files can be applied:
  • Stable kernel patches apply to the base kernel version. This means that the 2.6.17.10 patch will only apply to the 2.6.17 kernel release. The 2.6.17.10 kernel patch will not apply to the 2.6.17.9 kernel or any other release.
  • Base kernel release patches only apply to the previous base kernel version. This means that the 2.6.18 patch will only apply to the 2.6.17 kernel release. It will not apply to the last 2.6.17.y kernel release, or any other release.
  • Incremental patches upgrade from a specific release to the next release. This allows developers to not have to downgrade their kernel and then upgrade it, just to switch from the latest stable release to the next stable release (remember that the stable release patches are only against the base kernel, not the previous stable release.) Whenever possible, it is recommended that you use the incremental patches to make your life easier.
As we want to go from the 2.6.17.9 kernel release, to the 2.6.17.11 release, we will need to download two different patches. We will need a patch from the 2.6.17.9 release to the 2.6.17.10 release, and then from the 2.6.17.10 release to the 2.6.17.11 release.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Applying the patch
As the patches we have downloaded are compressed, the first thing to do is uncompress them with the bzip2 command:
$ bzip2 -dv patch-2.6.17.9-10.bz2
  patch-2.6.17.9-10.bz2: done
$ bzip2 -dv patch-2.6.17.10-11.bz2
  patch-2.6.17.10-11.bz2: done
$ ls -F
good_config linux-2.6.17.9/  patch-2.6.17.10-11  patch-2.6.17.9-10
Now we need to apply the patch files to the kernel directory. Go into the directory:
$ cd linux-2.6.17.9
            
and run the patch program to apply the first patch moving the source tree from the 2.6.17.9 to the 2.6.17.10 release:
$ patch -p1 < ../patch-2.6.17.9-10
patching file Makefile
patching file block/elevator.c
patching file fs/udf/super.c
patching file fs/udf/truncate.c
patching file include/net/sctp/sctp.h
patching file include/net/sctp/sm.h
patching file net/sctp/sm_make_chunk.c
patching file net/sctp/sm_statefuns.c
patching file net/sctp/socket.c
Verify that the patch really did work properly and that there are no errors or warnings in the output of the patch program. It is also a good idea to look at the Makefile of the kernel to see the kernel version:
$ $ head -n 5 Makefile
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 17
EXTRAVERSION = .10
NAME=Crazed Snow-Weasel
Now that the kernel is at the 2.6.17.10 release level, do the same thing as before and apply the patch to bring it up to the 2.6.17.11 level:
$ patch -p1 < ../patch-2.6.17.10-11
patching file Makefile
patching file arch/ia64/kernel/sys_ia64.c
patching file arch/sparc/kernel/sys_sparc.c
patching file arch/sparc64/kernel/sys_sparc.c
patching file drivers/char/tpm/tpm_tis.c
patching file drivers/ieee1394/ohci1394.c
patching file drivers/md/dm-mpath.c
patching file drivers/md/raid1.c
patching file drivers/net/sky2.c
patching file drivers/pci/quirks.c
patching file drivers/serial/Kconfig
patching file fs/befs/linuxvfs.c
patching file fs/ext3/super.c
patching file include/asm-generic/mman.h
patching file include/asm-ia64/mman.h
patching file include/asm-sparc/mman.h
patching file include/asm-sparc64/mman.h
patching file kernel/timer.c
patching file lib/spinlock_debug.c
patching file mm/mmap.c
patching file mm/swapfile.c
patching file net/bridge/netfilter/ebt_ulog.c
patching file net/core/dst.c
patching file net/core/rtnetlink.c
patching file net/ipv4/fib_semantics.c
patching file net/ipv4/netfilter/arp_tables.c
patching file net/ipv4/netfilter/ip_tables.c
patching file net/ipv4/netfilter/ipt_ULOG.c
patching file net/ipv4/route.c
patching file net/ipx/af_ipx.c
patching file net/netfilter/nfnetlink_log.c
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Reconfigure the kernel
Previously, we used the make menuconfig or gconfig or xconfig method to change different configuration options. But once you have a working configuration, the only thing that is necessary is to update it with any new options that have been added to the kernel since the last release. To do this, the make oldconfig and make silentoldconfig options should be used.
make oldconfig takes the current kernel configuration in the .config file, and updates it based on the new kernel release. To do this, it prints out all configuration questions, and provides an answer for them if the option is already handled in the configuration file. If there is a new option, the program stops and asks the user what the new configuration value should be set to. After answering the prompt, the program continues on until the whole kernel configuration is finished.
make silentoldconfig works exactly the same way as oldconfig does, but it does not print anything to the screen, unless it needs to ask a question about a new configuration option.
Usually, when upgrading between different versions of the stable releases, no new configuration options are added, as this is supposed to be a stable kernel series. If this happens, there are no new questions that need to be answered for the kernel configuration, so the program continues successfully without any need for user intervention. An example of this is moving from the 2.6.17.9 to 2.6.17.11 release:
$ cd linux-2.6.17.11
$ make silentoldconfig
scripts/kconfig/conf -s arch/i386/Kconfig
#
# using defaults found in .config
#
An example for where a new kernel option shows up in a new release is the following. The kernel option to enable Mutex debugging is a new one when switching between certain kernel releases. Here is the output when this happened:
$ make silentoldconfig
scripts/kconfig/conf -s arch/i386/Kconfig
#
# using defaults found in .config
#
*
* Restart config...
*
*
* Kernel hacking
*
Show timing information on printks (PRINTK_TIME) [Y/n/?] y
Magic SysRq key (MAGIC_SYSRQ) [Y/n/?] y
Kernel debugging (DEBUG_KERNEL) [Y/n/?] y
  Kernel log buffer size (16 => 64KB, 17 => 128KB) (LOG_BUF_SHIFT) [16] 16
  Detect Soft Lockups (DETECT_SOFTLOCKUP) [Y/n/?] y
  Collect scheduler statistics (SCHEDSTATS) [N/y/?] n
  Debug slab memory allocations (DEBUG_SLAB) [Y/n/?] y
    Memory leak debugging (DEBUG_SLAB_LEAK) [Y/n] y
  Mutex debugging, deadlock detection (DEBUG_MUTEXES) [N/y/?] (NEW) y
            
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Can't this be automated?
The whole process of downloading the proper patch file, uncompressing it, and then applying it seems to be ripe for automating. Kernel developers being the type that like to automate repetitive tasks, the program ketchup has been created to handle all of this automatically. See for more details on how this program works and how to use it.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 7: Customizing a Kernel
One of the hardest parts of building your own version of the Linux kernel is determining exactly which drivers and configuration options are needed for your machine to work properly. This chapter will walk you through this process of finding and selecting the correct drivers.
One of the easiest ways to determine which modules are necessary is to start with the kernel configuration that comes with your distribution's kernel package. It is also much easier to determine which drivers are needed on a running system, where the proper drivers are already bound to the hardware.
If you do not already have a Linux distribution installed on the machine that you are building the kernel for, use a LiveCD version of a distribution. This allows you to boot Linux on the machine and determine what kernel configuration options are needed in order to get the hardware working properly.
Almost all distributions provide the kernel configuration files as part of the distribution kernel package. Read the distribution-specific documentation for how to find these configurations. It is usually somewhere below the /usr/src/linux/ directory tree.
If the kernel configuration is hard to find, look in the kernel itself. Most distribution kernels are built to include the configuration within the /proc filesystem. To determine if this is true for your running kernel, enter:
$ ls /proc/config.gz
/proc/config.gz
If the /proc/config.gz filename is present, copy this file to your kernel source directory and uncompress it:
$ cp /proc/config.gz ~/linux/
$ cd ~/linux
$ gzip -dv config.gz
config.gz:       74.9% -- replaced with config
Copy this configuration file into your kernel directory and rename it to .config. Then use it as the basis of the kernel configuration to build the kernel as described in .
Using this configuration file should always generate a working kernel image for your machine. The disadvantage of this kernel image is that you will have built almost every kernel module and driver that is present in the kernel source tree. This is almost never needed for a single machine, so you can start to turn off different drivers and options that are not needed. It is recommended that you disable only those options that you are sure you do not need, as there might be parts of the system that rely on specific options to be enabled.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using a Distribution Kernel
One of the easiest ways to determine which modules are necessary is to start with the kernel configuration that comes with your distribution's kernel package. It is also much easier to determine which drivers are needed on a running system, where the proper drivers are already bound to the hardware.
If you do not already have a Linux distribution installed on the machine that you are building the kernel for, use a LiveCD version of a distribution. This allows you to boot Linux on the machine and determine what kernel configuration options are needed in order to get the hardware working properly.
Almost all distributions provide the kernel configuration files as part of the distribution kernel package. Read the distribution-specific documentation for how to find these configurations. It is usually somewhere below the /usr/src/linux/ directory tree.
If the kernel configuration is hard to find, look in the kernel itself. Most distribution kernels are built to include the configuration within the /proc filesystem. To determine if this is true for your running kernel, enter:
$ ls /proc/config.gz
/proc/config.gz
If the /proc/config.gz filename is present, copy this file to your kernel source directory and uncompress it:
$ cp /proc/config.gz ~/linux/
$ cd ~/linux
$ gzip -dv config.gz
config.gz:       74.9% -- replaced with config
Copy this configuration file into your kernel directory and rename it to .config. Then use it as the basis of the kernel configuration to build the kernel as described in .
Using this configuration file should always generate a working kernel image for your machine. The disadvantage of this kernel image is that you will have built almost every kernel module and driver that is present in the kernel source tree. This is almost never needed for a single machine, so you can start to turn off different drivers and options that are not needed. It is recommended that you d