Candidates should be able to properly configure a kernel to include or
disable specific features of the Linux kernel as necessary. This
objective includes compiling and recompiling the Linux kernel as needed,
updating and noting changes in a new kernel, creating an
initrd image and installing new kernels.
Key files, terms and utilities include:
make config, xconfig, menuconfig, oldconfig, mrproper, zImage, bzImage, modules, modules_install |
| mkinitrd (both Red hat and Debian based) |
/usr/src/linux |
/etc/lilo.conf |
/boot/grub/menu.lst or /boot/grub/grub.conf |
The kernel sources for the latest Linux kernel can be found at The Linux Kernel Archives .
The generic filename is always in the form
linux-kernel-version.tar.gz
or
linux-kernel-version.tar.bz2.
For example, linux-2.4.18.tar.gz is the kernel
archive for version “2.4.18”.
A common location to store and unpack kernel sources is
/usr/src.
If there is not enough free space on /usr/src to
unpack the sources, it is also possible to unpack the source in a different
directory. Creating a soft-link after unpacking from
/usr/src/linux to the linux
subdirectory in that location ensures easy access to the source.
The source code is available as a compressed tar archive, compressed either using
gzip (.gz extention) or
bzip2 (.bz2 extention).
The archive can be decompressed using gunzip
or bunzip2 followed by unpacking the resulting
archive with tar, or directly with
tar using the z
(.gz) or j
(.bz2) options:
# gunzip linux-2.4.18.tar.gz
# tar xf linux-2.4.18.tar
or
# tar xjf linux-2.4.18.tar.bz2
See manpages for tar, gzip, bzip2 for more information.
The first step in compiling a kernel is setting up the kernel
configuration which is saved in the .config file.
There are more than 500 options for the kernel, such as filesystem,
SCSI and networking support. Many of the options list kernel features
that can be either compiled directly into the kernel or compiled as
modules.
Some selections imply a group of other selections. For example, when you indicate that you wish to include SCSI support, additional options become available for specific SCSI drivers and features.
The results of all of these choices are stored in the kernel
configuration file /usr/src/linux/.config, which
is a plain text file that lists the options as shell variables.
To begin, set the current working directory to the top of the source tree:
# cd /usr/src/linux
There are several ways to set up .config. Although
you can do so, you should not edit the file manually. Instead,
select one of the three interactive approaches. An additional option is
available to construct a default configuration. Each set up is started
using make.
Running make config is the most rudimentary of the
automated kernel-configuration methods and does not depend on
full-screen display capabilities of your terminal. The system
presents a sequence of questions concerning kernel options.
This method can, admittedly, get a bit tedious and has the
disadvantage that you must answer all the questions before being able
to save your .config file and exit. However, it
is helpful if you do not have sufficient capability to use one of the
menu-based methods. A big drawback is that you can't move back and
forward through the various questions. An example session looks like
this:
# make config
rm -f include/asm
( cd include ; ln -sf asm-i386 asm)
/bin/sh scripts/Configure arch/i386/config.in
#
# Using defaults found in arch/i386/defconfig
#
*
* Code maturity level options
*
Prompt for development and/or incomplete code/drivers \
(CONFIG_EXPERIMENTAL) [N/y/?] y
*
* Loadable module support
*
Enable loadable module support (CONFIG_MODULES) [Y/n/?]
This configuration method is more intuitive and can be used as an alternative to make config. It creates a text-mode-windowed environment where you may use arrow and other keys to configure the kernel. The make menuconfig command is illustrated below in an xterm.

The make menuconfig menu display.
If you are running the X Window System, the make xconfig command presents a GUI menu with radio buttons to make the selections. The figure below illustrates the top-level make xconfig window.

The make xconfig top-level window.
The make oldconfig command creates a new
.config file, using the old
.config and options found in the source, only
requiring user interaction for options that that were previously not
configured (new options), for instance after addition of new
functionality, of upgrading to a later kernel release.
When using the .config from a previous kernel
release, first copy the .config from the
previous kernel-version to the /usr/src/linux/
directory and then run make oldconfig. The
.config will be moved to
.config.old and a new .config
is created. You will only be prompted for the answers to
new questions; the questions for which no answer can be found
in the .config.old file.
.config before
upgrading the kernel source, because the distribution might contain
a default .config file, overwriting your old
file.
.config
file, using the current .config and (new default)
options found in the source code. As a result
.config will contain at least all the previously
set and the new default options after writing the new
.config file and exiting the session without any
manual changes.
The dep object examins source files for
dependencies. The resulting table of dependencies is stored in a
file called .depend. There will be a
.depend file in each directory containing source
files. The .depend files are automatically
included in subsequent make operations.
The “clean” object removes old output files that may exist from previous kernel builds. These include core files, system map files and others.
The zImage and bzImage objects both effectively build the kernel. The difference between these two is explained in another paragraph.
After compilation the kernel image can be found in the
/usr/src/linux/arch/i386/boot directory (on i386 systems).
After the new kernel has been compiled, the system can be configured to boot it.
The first step is to put a copy of the new bzImage
on the boot partition. The name of the kernel file should preferably contain the kernel-version number, for example: vmlinuz-2.4.10:
# cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz-2.4.10
The currently available kernel versions can be found in the directory
/boot/ as shown below:
# ls -l /boot
-rw-r--r-- 1 root root 426824 Mar 23 2001 vmlinuz-2.2.18pre21
-rw-r--r-- 1 root root 739881 Sep 27 10:42 vmlinuz-2.4.10
-rw-r--r-- 1 root root 728156 Sep 21 15:24 vmlinuz-2.4.9
Next, configure the bootmanager to contain the new kernel.
lilo.conf could look like this:
# Boot up this one by default.
default=vmlinuz-2410
image=/boot/vmlinuz-2.4.10
label=linux-2410
read-only
image=/boot/vmlinuz-2.4.9
label=linux-249
read-only
image=/boot/vmlinuz-2.2.18pre21
label=linux-2218
read-only
Run lilo to add the new kernel and reboot to activate the new kernel.
Another way to enable the new kernel is by creating symbolic links in
the root directory to the kernel images in
/boot. It is a good practice to have at least
two kernels available: the kernel that has been used so far (and
which is working properly) and the newly compiled one (which might
not work since it hasn't been tested yet). One is called
vmlinuz and the other is called
vmlinuz.old. Like this the labels in
/etc/lilo.conf don't need to be changed after
installation of a new kernel.
First point vmlinuz.old to the latest known-working kernel image (in our example: /boot/vmlinuz-2.4.9) and point vmlinuz to the new kernel image (in our example: /boot/vmlinuz-2.4.10):
# ls -l vmlinuz*
lrwxrwxrwx 1 root root 19 Sep 19 17:33 vmlinuz -> /boot/vmlinuz-2.4.9
lrwxrwxrwx 1 root root 25 Sep 19 17:33 vmlinuz.old -> /boot/vmlinuz-2.2.18pre21
# rm /vmlinuz.old
# ln -s /boot/vmlinuz-2.4.9 /vmlinuz.old
# rm /vmlinuz
# ln -s /boot/vmlinuz-2.4.10 /vmlinuz
lilo.conf could look like this:
# Boot up this one by default.
default=Linux
image=/vmlinuz
label=Linux
read-only
image=/vmlinuz.old
label=LinuxOLD
read-only
Run lilo to add the new kernel and reboot to activate.
# lilo
Added Linux *
Added LinuxOLD
If the new kernel doesn't work, reboot again, press SHIFT to have the LILO boot loader activate the boot menu and select the last known working kernel to boot.
lilo.conf, otherwise the new kernel can't be
booted because lilo.conf is not consulted at
boot time.
The GRUB bootloader is described in the section called “ GRUB explained ”. As is the case with LILO both version specific and fixed kernel image names can be used with GRUB.
An example kernel configuration entry in
/boot/grub/menu.lst (or
/boot/grub/grub.conf) is provided:
title GNU/Linux, kernel 2.6.8
root (hd0,0)
kernel /boot/vmlinuz-2.6.8 root=/dev/hda1 ro
initrd /boot/initrd.img-2.6.8
savedefault
boot
The list of key files, terms and utilities also mentions mkinitrd. The following text can be found on The Linux Head Quarters :
Using the initial RAM disk (
initrd)
initrdadds the capability to load a RAM disk by the boot loader. This RAM disk can then be mounted as the root filesystem and programs can be run from it. Afterwards, a new root filesystem can be mounted from a different device. The previous root (frominitrd) is then either moved to the directory/initrdor it is unmounted.
initrdis mainly designed to allow system startup to occur in two phases, where the kernel comes up with a minimum set of compiled-in drivers, and where additional modules are loaded frominitrd.Operation
When using
initrd, the system boots as follows:
the boot loader loads the kernel and the initial RAM disk
the kernel converts
initrdinto a “normal” RAM disk and frees the memory used byinitrd.
initrdis mounted read-write as rootlinuxrc is executed (this can be any valid executable, including shell scripts; it is run with uid 0 and can do basically everything init can do)
when linuxrc terminates, the “real” root filesystem is mounted
if a directory
/initrdexists, theinitrdis moved there, otherwise,initrdis unmountedthe usual boot sequence (e.g. invocation of /sbin/init ) is performed on the root filesystem
Note that moving
initrdfrom/to/initrddoes not involve unmounting it. It is therefore possible to leave processes running oninitrd(or leave filesystems mounted, but see below) during that procedure. However, if/initrddoesn't exist,initrdcan only be unmounted if it is not used by anything. If it can't be unmounted, it will stay in memory.Also note that filesystems mounted under
initrdcontinue to be accessible, but their/proc/mountsentries are not updated. Also, if/initrddoesn't exist,initrdcan't be unmounted and will “disappear” and take those filesystems with it, thereby preventing them from being re-mounted. It is therefore strongly suggested to generally unmount all filesystems (except of course for the root filesystem, but including/proc) before switching frominitrdto the “normal” root filesystem.In order to de-allocate the memory used for the initial RAM disk, you have to execute freeramdisk after unmounting
/initrd.
initrdadds the following new options to the boot command line options:Loads the specified file as the initial RAM disk. When using LILO, you have to specify the RAM disk image file in
/etc/lilo.conf, using the INITRD configuration variable.noinitrd
initrddata is preserved but it is not converted to a RAM disk and the “normal” root filesystem is mounted.initrddata can be read from/dev/initrd. Note that the data ininitrdcan have any structure in this case and doesn't necessarily have to be a filesystem image. This option is used mainly for debugging.Note that
/dev/initrdis read-only and that it can only be used once. As soon as the last process has closed it, all data is freed and/dev/initrdcan't be opened any longer.root=/dev/ram
initrdis mounted as root, and /linuxrc is started. If no /linuxrc exists, the normal boot procedure is followed, with the RAM disk still mounted as root. This option is mainly useful when booting from a floppy disk. Compared to directly mounting an on-disk filesystem, the intermediate step of going viainitrdadds a little speed advantage and it allows the use of a compressed file system. Also, together with LOADLIN you may load the RAM disk directly from CDrom or disk, hence having a floppy-less boot from CD, e.g.: E:\loadlin E:\bzImage root=/dev/ram initrd=E:\rdimageInstallation
First, the “normal” root filesystem has to be prepared as follows:
# mknod /dev/initrd b 0 250 # chmod 400 /dev/initrd # mkdir /initrdIf the root filesystem is created during the boot procedure (i.e. if you're creating an install floppy), the root filesystem creation procedure should perform these operations.
Note that neither
/dev/initrdnor/initrdare strictly required for correct operation of initrd, but it is a lot easier to experiment withinitrdif you have them, and you may also want to use/initrdto pass data to the “real” system.Second, the kernel has to be compiled with RAM disk support and with support for the initial RAM disk enabled. Also, all components needed to execute programs from
initrd(e.g. executable format and filesystem) must be compiled into the kernel).Third, you have to create the RAM disk image. This is done by creating a filesystem on a block device and then by copying files to it as needed. With recent kernels, at least three types of devices are suitable for that:
a floppy disk (works everywhere but it's painfully slow) a RAM disk (fast, but allocates physical memory) a loopback device (the most elegant solution)
We'll describe the RAM disk method:
make sure you have a RAM disk device
/dev/ram(block, major 1, minor 0)create an empty filesystem of the appropriate size, e.g.
# mke2fs -m0 /dev/ram 300 (if space is critical, you may want to use the Minix FS instead of Ext2)
mount the filesystem on an appropriate directory, e.g.
# mount -t ext2 /dev/ram /mnt
create the console device:
# mkdir /mnt/dev # mknod /mnt/dev/tty1 c 4 1
copy all the files that are needed to properly use the
initrdenvironment. Don't forget the most important file, /linuxrc Note that /linuxrc must be given execute permission.unmount the RAM disk
# umount /dev/ram
copy the image to a file
# dd if=/dev/ram bs=1k count=300 of=/boot/initrd
deallocate the RAM disk
# freeramdisk /dev/ram
For experimenting with
initrd, you may want to take a rescue floppy (e.g. rescue.gz from Slackware) and only add a symbolic link from /linuxrc to /bin/sh, e.g.
# gunzip /dev/ram # mount -t minix /dev/ram /mnt # ln -s /bin/sh /mnt/linuxrc # umount /dev/ram # dd if=/dev/ram bs=1k count=1440 of=/boot/initrd # freeramdisk /dev/ram
Finally, you have to boot the kernel and load
initrd. With LOADLIN, you simply executeLOADLIN initrd= e.g. LOADLIN C:\LINUX\VMLINUZ initrd=C:\LINUX\INITRD
With LILO, you add the option INITRD= to either the global section or to the section of the respective kernel in
/etc/lilo.conf, e.g.image = /vmlinuz initrd = /boot/initrd
and run /sbin/lilo
Now you can boot and enjoy using
initrd.Setting the root device
By default, the standard settings in the kernel are used for the root device, i.e. the default compiled in or set with rdev , or what was passed with root=xxx on the command line, or, with LILO, what was specified in
/etc/lilo.confIt is also possible to useinitrdwith an NFS-mounted root; you have to use the nfs_root_name and nfs_root_addrs boot options for this.It is also possible to change the root device from within the
initrdenvironment. In order to do so,/prochas to be mounted. Then, the following files are available:/proc/sys/kernel/real-root-dev /proc/sys/kernel/nfs-root-name /proc/sys/kernel/nfs-root-addrsreal-root-dev can be changed by writing the number of the new root FS device to it, e.g.
# echo 0x301 >/proc/sys/kernel/real-root-devfor
/dev/hda1. When using an NFS-mounted root, nfs-root-name and nfs-root-addrs have to be set accordingly and then real-root-dev has to be set to 0xff, e.g.# echo /var/nfsroot >/proc/sys/kernel/nfs-root-name # echo 193.8.232.2:193.8.232.7::255.255.255.0:idefix \ >/proc/sys/kernel/nfs-root-addrs # echo 255 >/proc/sys/kernel/real-root-devIf the root device is set to the RAM disk, the root filesystem is not moved to
/initrd, but the boot procedure is simply continued by starting init on the initial RAM disk.Usage scenarios
The main motivation for implementing
initrdwas to allow for modular kernel configuration at system installation. The procedure would work as follows:
systems boots from floppy or other media with a minimal kernel (e.g. support for RAM disks,
initrd,a.out, and the ext2 FS) and loadsinitrd/linuxrc determines what is needed to (1) mount the “real” root FS (i.e. device type, device drivers, filesystem) and (2) the distribution media (e.g. CD-ROM, network, tape, ...). This can be done by asking the user, by auto-probing, or by using a hybrid approach.
/linuxrc loads the necessary modules
/linuxrc creates and populates the root file system (this doesn't have to be a very usable system yet)
/linuxrc unmounts the root filesystem and possibly any other filesystems it has mounted, sets
/proc/sys/kernel/..., and terminatesthe root filesystem is mounted
now that we're sure that the filesystem is accessible and intact, the boot loader can be installed
the boot loader is configured to load an
initrdwith the set of modules that was used to bring up the system (e.g./initrdcan be modified, then unmounted, and finally, the image is written from/dev/ramto a file)now the system is bootable and additional installation tasks can be performed
The key role of
initrdhere is to re-use the configuration data during normal system operation without requiring the use of a bloated “generic” kernel or re-compilation or re-linking of the kernel.A second scenario is for installations where Linux runs on systems with different hardware configurations in a single administrative domain. In such cases, it is desirable to generate only a small set of kernels (ideally only one) and to keep the system-specific part of configuration information as small as possible. In this case, a common
initrdcould be generated with all the necessary modules. Then, only /linuxrc or a file read by it would have to be different.A third scenario might result in more convenient recovery disks, because information like the location of the root FS partition doesn't have to be provided at boot time, and the system loaded from
initrdcan use a user-friendly dialog and can also perform some sanity checks (or even some form of auto-detection).Last but not least, CDrom distributors may use it for better installation from CD, either using a LILO boot floppy and bootstrapping a bigger ramdisk via
initrdfrom CD, or using LOADLIN to directly load the ramdisk from CD without need of floppies.Since
initrdis a fairly generic mechanism, it is likely that additional uses will be found.