Computers run programs. From the earliest behemoth computers with their hard-wired programs to modern-day disposable calculators and desktop PCs, all our computers run some kind of program. John von Neumann cooked up the concept of storing a computer's program just like any other piece of data, making way for computers to become multipurpose tools no longer locked in to one hard-wired function. Soon the concept of an operating system, or a program to abstract common system-level details like device management and program execution, was born. It didn't take long for some crafty system programmers to realize that a single CPU could be made to perform multiple tasks seemingly at the same time. This gave rise to the first time-sharing and multitasking/multiuser operating systems. All modern computers still operate on this same stored program concept. In the case of a modern personal computer, after switching it on, it runs the stored program in the BIOS, or firmware, which eventually hands off to a multistage bootloader, which in turn loads the OS kernel. The kernel executes and sets up an operating environment in which system resources like CPU time, memory and devices can be used by programs executed beneath the kernel. It's all a long chain of stored programs.
The kernel is a program just like any other (albeit a rather complex one). So, what stops you from executing the kernel just like any other program? Actually, not much at all. This is what user-mode Linux (UML) is all about.
The Linux kernel normally runs with special privileges, because it needs direct access to your hardware. User-mode Linux provides a way to compile the normal Linux kernel sources so that it can be invoked as a regular binary program on top of the base Linux kernel. When you run a kernel on top of the base Linux kernel, you are really running one or more “guest” Linux systems without any special privileges. (There are some exceptions. Some software must be installed as root for user-mode Linux to work.) These guest Linux systems are complete systems that run in a (mostly) safe environment.
In the remainder of this article, I provide a recipe for getting a UML system up and running on your host Linux box. Then, we explore some features and have some fun. The host system I am using for this demonstration is Fedora Core 4 on an Intel P4 with 1GB of memory, but almost any system and distribution will work, provided it is running a recent 2.6 kernel and has a minimum of 256MB of memory.
A guest UML system is just like any other Linux system. It is a combination of a Linux kernel and a collection of small programs, libraries and files that make up the operating system. These are provided in two parts, the kernel and a filesystem image. A filesystem image is a virtual disk partition. This is what will be mounted and used as the root filesystem of our UML system. You have the choice to create these two parts yourself or download them off the Net, ready made from popular distributions. In the interest of instant gratification, we take the ready-made route; take a look at the UML Wiki for more information on building your own filesystems (see the on-line Resources).
Kernels and root filesystem images are available in a number of versions and distributions. Images of Red Hat, Fedora Core, Debian and a number of special-purpose distributions are available. I use Debian 3.1 for this demonstration.
User-mode Linux has one very special feature called a Copy-On-Write file or COW. Copy on write is a common computer science concept that defines a mechanism for a chunk of data to remain read-only yet allows modification by writing changed data blocks to an alternate location. The filesystem image you download always remains read-only. Changes made to the filesystem in our running UML system are written to the COW file. This allows us to boot up multiple UML systems from the same read-only root filesystem image, provided they all have separate COW files. Also, if our UML system becomes corrupted, we simply clear the COW file to start over. The COW files are what is called sparse files; even though they may appear to be big when viewing the file size, only non-null data is actually allocated space on the disk.
Let's start by collecting the components in a freshly created empty directory. Make sure sufficient disk space is available; after all, we need to house an entire Debian installation. Three gigabytes should be sufficient for the basic system. Download the Debian-3.1-x86-root_fs.bz2 file from uml.nagafix.co.uk. Then, grab the 220.127.116.11-bs3 UML kernel from www.user-mode-linux.org/~blaisorblade/binaries. Finally, grab the UML utilities sources from user-mode-linux.sourceforge.net/dl-sf.html. If any of these files are missing, you can find alternate download locations in the Resources for this article.
Below is a script of the commands for collecting all the parts and compiling the UML utilities that are available only in source form. If you are not interested in setting up networking, you can omit the uml_utilities tarball and skip the compile. All the steps below can be performed as a normal user except the installation of the UML utilities, which requires an su to root:
mkdir /tmp/UML-Demo cd /tmp/UML-Demo wget http://uml.nagafix.co.uk/Debian-3.1/ -->Debian-3.1-x86-root_fs.bz2 bunzip2 Debian-3.1-x86-root_fs.bz2 wget http://www.user-mode-linux.org/~blaisorblade/binaries/ -->18.104.22.168-bs3/uml-release-22.214.171.124-bs3.tar.bz2 tar -xvjf uml-release-126.96.36.199-bs3.tar.bz2 cp um32-2.6.14-release-mod/vmlinux-188.8.131.52-bs3 . wget http://mirror.usermodelinux.org/uml/ -->uml_utilities_20040406.tar.bz2 tar -xvjf uml_utilities_20040406.tar.bz2 cd tools make all su root make install DESTDIR=/ exit cd ..
Now we have all the parts collected and are ready to rock 'n' roll. All Linux systems have a kernel command line. In most systems, this command line is invoked by the bootloader (GRUB, LILO and so on). In our case, we compose the command line ourselves to instruct the kernel to use the Debian root filesystem image and a COW file named Debian1.cow as its root (/) filesystem. Your current terminal becomes the console of the guest UML system:
cd /tmp/UML-Demo ./vmlinux-184.108.40.206-bs3 -->ubd0=Debian1.cow,Debian-3.1-x86-root_fs root=/dev/ubda
After that command is executed, we see the familiar Linux kernel boot messages ending with a Debian system waiting for someone to log in. We can log in as root (there is no password) and poke around as shown in Listing 1.