Problem solve Get help with specific problems with your technologies, process and projects.

Testing a new Linux kernel while keeping the old one

This article describes how you can test out the most recent kernel release safely by creating a dual-boot system with two Linux kernels.

I was running SUSE Linux 9.0 on an IBM ThinkPad. This configuration did everything I needed: word processing, Web access, email, C and assembly programming. But my version of the Linux kernel was out of date and I wanted to upgrade it. I wanted to do this in a way that did not remove my current kernel, in case I needed to revert to it.

This article describes how I accomplished this task by using a dual-boot system with two Linux kernels to choose from during startup. You can use this same approach to upgrade to a new, stable version of the kernel or to test a potentially unstable kernel before committing to it.

I began with the SUSE kernel labeled 2.4.21-99-default. Also installed on my SUSE system (from installation disks) were the following items related to kernel compilation: KDE 3.1, ncurses 5.3, gcc 3.3.1, YaST2, GRUB and mkinitrd. My goal was to add kernel version 2.6.17, which was the latest at the time of my project. This was the process I followed.

The first step is to retrieve the kernel source code.

  1. Browse to using a FTP-capable tool like Internet Explorer or Mozilla Firefox.

  2. Navigate to /pub/linux/kernel/2.6/.

  3. Download linux-2.6.17.tar.gz.

  4. Open a KDE session as root on Linux.

  5. Transfer linux-2.6.17.tar.gz to /root/Desktop/.

Next, open Ark and choose to decompress /root/Desktop/linux-2.6.17 to /usr/src/. The folder /usr/src/linux-2.6.17/ now exists containing the kernel source. To follow conventions, create a symbolic linked called /usr/src/linux to the actual source folder by opening Konsole and navigating to /usr/src/. Issue the command ln -s /usr/src/linux-2.6.17 /usr/src/linux. (This is not the same as right clicking in Konqueror and selecting "Link to Location.")

To begin the compilation process, navigate in Konsole to /usr/src/linux/. Then issue the command make menuconfig. This command compiles the application, the menu, which creates a configuration file for you. (Other configuration methods may use different interface mechanisms with similar results.) If you see a stream of errors originating with one saying that ./scripts/kconfig/lxdialog/curses.h is missing, then you need an add-on package for ncurses, which is available here.

Double click on the file icon to preview the package in Konqueror. Click "Install package with YaST." A conflict warning may appear saying that it needs a later version of ncurses itself. If so, download that here and install it. (Conflict warnings may persist, but you can ignore them.)

Following the installation of the ncurses packages (if necessary), retry make menuconfig A torrent of compiler warnings may appear which you can ignore. A moment later, however, the menu should open up. On the menu, review the options carefully. In general, you should leave the options as they are configured. But you may want to add options that you know you will use, such as items related to security or laptops.

Exit the menu, and save the configuration. It will be saved in /usr/src/linux/.config.

Some Linux guides tell you to run make dep at this point. As of 2.6.x, this step is no longer needed and it does nothing.

The next step is to actually start to compile the kernel from source code. The kernel itself is called a kernel image. To create it, run make zImage. Compilation should start and go on for quite a while. If it stops and says that the system is too big, run make bzImage. (Do not start over; just do it now.) The final product, the kernel image, will now reside in /usr/src/linux/arch/i386/boot/zImage or /usr/src/linux/arch/i386/boot/bzImage, depending on which make command was the last one issued. I am going to assume the kernel image is called bzImage, but change the instructions below to zImage if necessary.

Now the kernel is made. The next step is to make the computer boot up using that kernel.

  1. Copy the kernel image to /boot/ because that is where kernels generally reside. I named mine bzImage-2.6.17. (You should follow the naming convention something-X.X.XX, wherein X.X.XX is the kernel version number.)

  2. Make a symbolic link from /boot/bzImage to /boot/bzImage-2.6.17. (The command is ln –s /boot/bzImage-2.6.17 /boot/bzImage).

  3. Copy /usr/src/linux/ to /boot/ and call it

  4. Create a symbolic link from /boot/ to /boot/

The necessary files should now be in place. Notice that I did not modify the old kernel, called vmlinuz-2.4.21-99-default or the symbolic link to that called vmlinuz.

The boot loader, GRUB, presents a menu on startup of which OS to load. You are going to add the new kernel to that list without removing the old kernel from the list. The GRUB configuration file is called /boot/grub/menu.lst.

  1. Find the entry for the old kernel, and made a copy of it underneath itself.

  2. Change the "title" line.

  3. Change /boot/vmlinuz to /boot/bzImage.

  4. Change /boot/initrd to /boot/initrd-2.6.17.

  5. Change any other kernel-specific filename.

You now have the full capabilities for both kernels and can choose which one to use when you start your computer.

(If you are using LILO as your boot loader, it will be more difficult to create this dual-boot scenario. Please let me know if you figure out how to do so, and I will publish the solution.)

This brings us to the last step. The initial ram disk image is a file that holds images of modules for the kernel to use before it can retrieve modules in the normal way from the hard drive. In this case, the disk image contains the module to access Linux's filesystem, and then the kernel can retrieve everything else it needs off the hard drive. Create a new ram disk image using the command mkinitrd -k /boot/bzImage –i /boot/initrd-2.6.17. (This file is already entered in /boot/grub/menu.lst.) Restart the computer, select the new kernel in the GRUB menu, and sit back. The screen may stay black for a minute, but eventually X should start, and soon after that the desktop should appear.

I will point out that these instructions produce a working, but vanilla, kernel that may need additional configuration depending on how you will use it. For example, my new kernel was not "laptop aware" (no standby on lid close). Hotplug services were also seemingly nonexistent. I believe these problems are related to the choice of options at the kernel configuration menu, and I hope to address them in a future article.

Editor's note: A reader submitted this in response to Charles Connell's article:

I've attached the configuration file for a lilo setup I have been using for about six months. The stuff at the top is global info. The kernel that boots by default is indicated in the default = line (in this case the 2.4.32 kernel). The individual kernel choices start with the image = lines. Originally only the vmlinuz-2.4.18-14 kernel was used. I have added the other 3 for a choice of 4 kernels. If I had used an identical setup to the original for the others, I could have simply copied the lines, substituting in the new kernel and ramdisk names as you did, and changing the label. (The label is what you specify at boot time to choose which image to boot, and the default= command uses it to identify the default image.) However, unlike the original entry, on my other entries I chose not to use a ramdisk, so I had to change the entries accordingly. (Actually, I didn't want to figure out how to create a ramdisk, so I just compiled everything I needed into the kernel.) The only significant difference between lilo and GRUB is that with lilo you must edit your /etc/lilo.conf file and have your kernels and any ramdisks in place, and *then* run the command "lilo" as root, which installs the updated bootloader. Lilo stores the physical locations (not the logical locations of the directory entries) of these files, so if these files get physically moved on the disk, you must again run the lilo command.

lilo.conf contents:



 root = /dev/hda3

image = /boot/vmlinuz-2.4.31
  label = linux-31
  root = /dev/hda3

image = /boot/vmlinuz-2.4.32
  label = linux
  root = /dev/hda3

Charles Connell IV is a high school student in Bedford, Mass. He can be reached at [email protected].

Dig Deeper on Linux servers