justlinux.com
Fri, 19-Mar-2010 16:04:17 GMT
internet.com
Forum: Registered Users: 73708, Online: 261
nhfs Here you can view your subscribed threads, work with private messages and edit your profile and preferences Registration is free! Calendar Find other members Frequently Asked Questions Search Home Home

Help File Library: The Kernel: Configuration and Compilation

Introduction

The odds are that every Linux user will have to compile a kernel at some point in their time, and it sometimes needs to be done straight after install to add support for the various hardware and peripherals you may need/want to use. This necessity makes it an important skill to master, especially for one new to Linux, and in this document I intend to run you through compiling a new kernel, patching up a kernel, and the basics of how the kernel development system works.

I'm going to make a few assumptions.

  • You have read about any dependency problems your kernel upgrade may produce. This warning mainly goes to those upgrading from Linux 2.0.x to 2.2.x. A good source of information on this is LinuxHQ
  • You have a bootdisk that works. We are going to be editing your bootmanager, and if things go wrong, you'll find that bootdisk comes in handy ;) If you don't have one, put a floppy in, and try issuing the following as root.
    dd if=/boot/bzImage of=/dev/fd0 bs=8192
    where /boot/bzImage is the location of your current kernel image
  • Your bootmanager is LILO. LILO is the default in most distributions these days.

If you have any suggestions regarding this document, please mail me.

The Linux Kernel: An Overview

I will not dwell on history here, and will also not attempt to provide an explanation as to how the Linux kernel functions. It is enough to say that it is a monolithic kernel, which in turn would require a monolithic explanation. ;)

Instead, I will cover some of the fundamental aspects of the linux kernel development, which will hopefully make the rest of this document a little clearer.

The kernel holds its version numbers within its filename, and are in the format linux-major.minor.patch Where major and minor are the version numbers, and patch is the patchlevel of that particular kernel version.

For example, linux-2.2.6 is patchlevel six, of kernel version 2.2

However, one important part of the development life cycle, is the release of 'development' kernel versions in other words these versions are not stable. To allow you to distinguish between the different kernel types, even numbered kernels (2.0 2.2 etc) are stable releases, and odd numbered kernels (2.1 2.3 etc) are the development releases.

How to Compile a Kernel

The Pre-Compilation Stage

  1. First of all, you'll want to download your new kernel. The example I am using is upgrading one my machines from 2.2.9 to 2.2.10, so you obviously need to amend your commands to mention your kernel numbers, not mine.
  2. Log in as root
  3. Copy your brand spanking new kernel to /usr/src/ I am assuming the file is a .tar.gz file. (Note: I know bzip is a better tool to use, but .tar.gz still seems to be the default).

    You'll see a few files in that directory. and they may require a little explaining. An example output of ls in /usr/src/ is shown below:

    ls
    linux/
    linux-2.2.9/
    linux-2.2.10.tar.gz
    linux-2.2.6/
    

    From the above list we can see the proposed kernel package (2.2.10), an old kernel source directory (2.2.6), and my current kernel sources (2.2.9).

    The directory called Linux is a symbolic link to whatever kernel source I am using at the time.. At this stage of the process it still points to linux-2.2.9/

    Now.. Your linux directory may not be a symbolic link.. it may just be a regular directory. I use symbolic links because it is a good way of making managing your kernel sources, without having to move a lot of files around, and reduces the risk of me losing old kernel sources. You do not need to use symbolic links, but i recommend it.

    You can check your Linux directory to see if it is a sym-link by typing
    ls -l linux and if you see something like linux -> linux-2.2.9 it means it is a sym-link.

    The reason for mentioning this is that if your linux directory is not a symbolic link, you may well want to rename it to something different, so as not lose the kernel source files. Either way, you need to remove the linux directory in /usr/src

  4. The next step is to type
    # rm linux
    
    This will get rid of that symbolic link to linux-2.2.9
  5. Type
    tar -xvzf linux-2.2.10.tar.gz
    
    to unpack the new kernel sources.If you look at the directory you will see a directory called linux with lots of lovely kernel-related stuff in there. Since I suggested you make linux a symbolic link, then that is what we do next.
  6. Type
    mv linux linux-2.2.10
    
    The new kernel sources are moved to a separate directory.
  7. Type
    ln -s linux-2.2.10 linux
    
    This will set up the new symbolic link
  8. Now you want to enter the directory /usr/src/linux to start compilation.

The Compilation Stage

There are too many options and possibilities in the kernel configuration options to cover them here, and the only advice I can give you whilst you are choosing which modules to add is to read all the help notes.. If in doubt read the help notes, and if you are still in doubt, go with the default option. A good book for an explanation on the various modules is Running Linux by (O'Reilly, 2000).

You have a number of ways of going through the possible modules to include.

  • make config - A sequential text-based selection method. Takes a looong time.
  • make menuconfig - A menu driven interface which works in X or at the CLI
  • make xconfig - A version of menuconfig for X Window if you have it running.
  • make zlilo - This command attempts to configure lilo to boot your new kernel, and although useful, can be somewhat unreliable, especially if you have complex lilo setups.

I would suggest one of the latter two options, for reasons of speed and sanity. There is nothing worse than going through a make config to realise you've forgotten something and you need to do it again.

There is also one other option worth mentioning, which is...
make oldconfig

This option looks in your /usr/src/linux directory for a file named .config This file contains all the compilation options you chose the last time you compiled your kernel. So if you are simply upgrading your kernel, and have the same requirements from your kernel, you can simply use this option to load your default values. Just make sure that your .config file from your old kernel source tree is copied into your new kernel source tree, and you will be able to apply the same values you compiled into your last kernel.

If you still need to make one or two changes to your old kernel configuration, that is easily done with xconfig, or menuconfig.

I cannot proceed any further without a brief discussion on the options in a kernel. You have one of three options for most configurable elements within a kernel; compile them in, don't compile them in, or add them as a module. Compiling them in means that this function/element will always be available in your new kernel, and the opposite applies if you do not compile an element in. Adding an option as a module, means that you can load the function at run-time.. i.e. after the kernel has booted. This allows you to keep the function available to you, yet still gain the benefits from having a small and fast kernel.

A modular approaches to kernels is best used for systems in flux.. computers that have components changed and/or removed frequently, or for systems that want more options. For example, if you have three soundcards for some reason, it is unlikely you will want to use them all at once, so why compile support for three different soundcards? just use each driver as a module, and load and unload them as necessary.

There are programs that handle the loading and unloading of modules, and some that even auto-load modules upon referencing the device the function is related to, but I will leave those programs beyond the scope of this document for now (unless enough of you tell me otherwise).

Anyway... after you've chosen all your modules, you need to perform the following steps

  1. Type
    make dep
    
  2. Type
    make clean
    
  3. Type
    make bzImage
    

    Note: You can substitiute bzImage with zImage. However bzImage makes the kernel smaller, which is a good idea in most cases.

  4. Type
    make modules
    
  5. If you are using, for example, kernel version 2.2.10, then when you issue the next command, the modules are installed in /lib/modules/<kernel_release>, so in this case /lib/modules/2.2.10. All well and good, except if this is not the first kernel you have compiled from this kernel release, then you are going to overwrite your modules. So, a good idea at this point is to move them out of the way. I usually perform a command similar to the following
    mv /lib/modules/<kernel_release> /lib/modules/<kernel_release.old>
    
  6. You can now enter the following command:
    make modules_install
    
    and your kernel is compiled!

If you have found one of your make commands exits with an error, the chances are you have chosen some conflicting modules. The solution? Go back to the make config/menuconfig/xconfig stage.

The Post-compilation Stage

This is the important stuff... you will now have to include your new configuration as an option in your bootmanager. The method I will describe is to add a new kernel to LILO. This way, you have the option of booting the new kernel as well as booting the old kernel, just in case there are any problems.

Your newly compiled kernel is in /usr/src/linux/arch/architecture/boot/ where /architecture is the type of computer you are using. If it's a plain vanilla PC (like mine), then you can substitiute /architecture with /i386. The kernel's name is bzImage (or if you used make zImage during compile, it will be zImage)

You must also know where you keep your current kernels. On my system it is /boot but some people use their root (/) directory.

Bearing in mind these specifics, follow these steps to begin the process:

  1. Type
    cd /boot
    
  2. Type
    mv bzImage  vmlinuz-2.2.9
    
    This renames the old kernel so you don't overwrite it.
  3. Type
    mv system.map  systemp.map-2.2.9
    
    This moves the old system map
  4. Now enter
    cp /usr/src/linux/arch/i386/boot/bzImage  /boot/
    
    which copies the new kernel to the boot directory
  5. Type
    cp /usr/src/linux/System.map  /boot/
    
    This copies the new system map to the boot directory

I will take moment here to discuss the System.map file, and the organisation of this directory in general. In the above example I have assumed that you have a static System.map you want to replace, although some systems have a symbolic link named system.map pointing to a different file. I have assumed this on the basis that most distributions install a static system.map file, and so if you don't know whether you have a static system.map file, or just a symbolic link to another file, the odds are you have a static one, and will be perfectly fine when following the instructions given.

It is important to remember the differences and filenames you've just changed, as they need to be reflected in your lilo configuration file, which can be configured by the following steps:

  1. Pull up /etc/lilo.conf with your favorite editor. If you have only one kernel in here, and you have no other OS on your system, their should only be one stanza relating to kernel locations and names. Other OS's you use will have identifiable labels. A stanza with a label=windows should be left alone. You only need to be concerned with your linux boot parameters.
  2. Find your old kernel's stanza... an example of what it may look like is shown below
    image = /boot/bzImage
    root = /dev/hda1
    label = linux
    

    As you remember, you changed my old bzImage to vmlinuzold so you need to edit that stanza to reflect the changes.
  3. Edit the file so it reads
    image = /boot/vmlinuzold
    root = dev/hda1
    label = old
    
  4. Add a new stanza for your new kernel. An example fromm my /etc/lilo.conf is:
    image = /boot/bzImage
    root = /dev/hda1
    label = new
    
  5. Now you need to save your lilo.conf and then run the following to update LILO:
    /sbin/lilo
    

If lilo gives output of options without any errors.. well... you've finished. All that remains is to reboot, and at the LILO prompt (attained by pressing Shift when the word LILO appears in the boot sequence) type your new kernel label, which in my case is "new". Obviously I'll leave out the inverted comma's :)

Once you've checked it by booting (keeping that boot floppy handy) and you are happy with it, you can edit /etc/lilo.conf once more, to make your new kernel the default kernel to boot. To do that, just make your new kernel's stanza the first one in the list of boot options. In our example, just switch the vmlinuzold stanza with the bzImage stanza.

Patching a Kernel

The advantage of patching an existing kernel as opposed to downloading the next kernel release, is that people with little time and/or bandwidth can keep their kernel up to date, just by applying a (typically) 20-KB patch file.

You need to download the patches you require in sequential order from the patchlevel of your current kernel source to the patchlevel you wish to upgrade to.

For example, if I had kernel 2.2.6 and I wanted to upgrade to kernel 2.2.11, I would need patches 2.2.7, 2.2.8, 2.2.9, and on through to 2.2.11. Kernel patches follow the same naming conventions as the kernel itself does. i.e., patch-2.2.8 is the patch to upgrade from 2.2.7 to 2.2.8.

You do not have to store your kernel patches in any specific location, rather it is the location where you execute the patch command that is important.

To patch your kernel, you must do the following as root.

  1. Type
    cd /usr/src
    
    You must execute your patch command from this location
  2. Type
    gunzip -c patchfile | patch -p0
    
    where patchfile is the name and location of your patch.

    Note: You run the patch command above for each patchfile in sequential order. Following the previous example, if I had kernel 2.2.6 and wanted to patch up to 2.2.11 I would first apply patch 2.2.7, followed by 2.2.8, 2.2.9, and on through to 2.2.11. You cannot use any wildcards such as * either, as this applies the patches in ASCII order, not numerical order.

  3. To make sure all the patches were applied successfully, issue the following commands as root:
    find /usr/src/linux -follow -name "*.rej" -print
    find /usr/src/linux -follow -name "*#" -print
    
    If either of the above two commands return any files, then some parts of the patch process could not be applied for some reason. If you are in doubt as to what action should be taken to address such problems, I would suggest you download a kernel source package, and start from the beginning.

If everything went cleanly, you have successfully patched your kernel source, and are free to compile a new up-to-date kernel.

Other Sources of Information

The documents in your kernel sources are the most detailed.. You should find them in /usr/src/linux/Documentation/. The Linux Documentation Project has a good selection of kernel info as well.

For those of you who want to download your kernels/patches, find your local mirror here


internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers
internet.commerce
Be a Commerce Partner












The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers