Rate this page del.icio.us  Digg slashdot StumbleUpon

Tip from RHCEs: Cows in the Linux kernel

by the editorial team

by Masatake Yamato and Ryoichiro Tsuruno

Note:
An article on building source can be found at fedoraproject.org. That article begins with this warning: “Do Not Build Packages as root. Building packages as root is inherently dangerous and not required, even for the kernel. The following instructions allow any normal user to install and build kernels from the source packages.”

While you deal with your daily chores, you may not have much chance or time to dig deep into Red Hat® Enterprise Linux® source code. When you face a problem, unlike other proprietary software, RHEL lets you access its source code freely as a last resort. Let’s go through how to access RHEL source code so that you will be well prepared when something calls for it. This guide will show you how you can enjoy the archeology of the linux kernel by digging into source code.

First, we get source rpm. Use rpm command to find kernel rpm name of current kernel you are using:

$ rpm -qi kernel
Name        : kernel                       Relocations: (not relocatable)
Version     : 2.6.18                            Vendor: Red Hat, Inc.
Release     : 8.1.14.el5                    Build Date: Wed Sep 26 01:17:11 2007
Install Date: Fri Oct 12 19:06:29 2007      Build Host: hs20-bc1-7.build.redhat.com
Group       : System Environment/Kernel     Source RPM: kernel-2.6.18-8.1.14.el5.src.rpm
Size        : 75881257                         License: GPLv2
Signature   : DSA/SHA1, Thu Sep 27 22:55:55 2007, Key ID 5326810137017186
Packager    : Red Hat, Inc. 
Summary     : The Linux kernel (the core of the Linux operating system)
Description :
The kernel package contains the Linux kernel (vmlinuz), the core of any
Linux operating system.  The kernel handles the basic functions
of the operating system:  memory allocation, process allocation, device
input and output, etc.

We now know it is kernel-2.6.18-8.1.14.el5. Use either wget or curl to download src.rpm.::

$ wget \
ftp.redhat.com:/pub/redhat/linux/enterprise/5Server/en/os/SRPMS/kernel-2.6.18-8.1.14.el5.src.rpm

Install src.rpm and build it.::

$ sudo rpm -ivh kernel-2.6.18-8.1.14.el5.src.rpm
$ sudo rpmbuild -bp –target=i686 –nodeps /usr/src/redhat/SPECS/kernel-2.6.spec

–target=XXX needs to be modified to suit your hardware architecture. It may take a while to execute above command. Built kernel source will be saved in /usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.i386:

$ cd /usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.i386
$ ls
-r--r--r-- 12 root root 18693  9 20  2006 COPYING
-r--r--r--  2 root root 89472  7 30 20:51 CREDITS
dr-xr-xr-x 59 root root  2048  9 21 02:56 Documentation
-r--r--r--  6 root root  1273  9 20  2006 Kbuild
-r--r--r--  2 root root 73609  7 30 20:51 MAINTAINERS
-r--r--r--  2 root root 47798  7 30 20:51 Makefile
-r--r--r--  6 root root 16538  9 20  2006 README
-r--r--r--  6 root root  3065  9 20  2006 REPORTING-BUGS
dr-xr-xr-x 26 root root  3864  7 31 00:40 arch
dr-xr-xr-x  2 root root  3864  9 12 00:28 block
dr-xr-xr-x  2 root root  3864  7 31 00:41 configs
dr-xr-xr-x  4 root root  3864  9 12 00:28 crypto
dr-xr-xr-x 62 root root  3864  9 12 00:27 drivers
dr-xr-xr-x 63 root root  2048  9 21 02:56 fs
dr-xr-xr-x 42 root root  3864  9 12 00:28 include
dr-xr-xr-x  2 root root  3864  9 12 00:27 init
dr-xr-xr-x  2 root root  3864  9 21 02:56 ipc
dr-xr-xr-x  5 root root  2048  9 21 02:56 kernel
dr-xr-xr-x  5 root root  2048  9 21 02:56 lib
dr-xr-xr-x  2 root root  3864  9 12 00:28 mm
dr-xr-xr-x 38 root root  3864  9 21 02:56 net
dr-xr-xr-x 10 root root  3864  9 21 02:56 scripts
dr-xr-xr-x  4 root root  3864  9 12 00:27 security
dr-xr-xr-x 17 root root  3864  9 21 02:56 sound
dr-xr-xr-x  2 root root  3864  9 21 02:56 usr

If you search under this directory, you may be able to find a solution to your software problem. Of course, finding it may require knowledge and experience. But please don’t stop reading yet. I have prepared a fun little tour in which you can learn kernel source code structure.

“Simply, I’d say that porting is impossible. It’s mostly in C, but most people wouldn’t call what I write C. It uses every conceivable feature of the 386 I could find, as it was also a project to teach me about the 386.” — Linus Torvalds

Linus Torvalds once said Linux would only run on a i386 architecture. As you already know, RHEL runs on many architectures: i686, x86_64, ia64 and ppc. On top of that, the Linux kernel runs on many more architectures. There are maintainers for each architecture and they lead architecture-specific development. We will focus on an architecture-dependent part of code in this exercise.

Architecture specific code is stored in arch/* and include/asm-*. In general, include/asm-* files define constants and arch/* stores
program codes that use these constants.

For example, HP PA-RISC specific source code is stored::

include/asm-parisc
arch/parisc

An example of architecture-specific code would be dealing with something that cannot be resolved inside the kernel such as running out of memory. As I was researching such code, I excavated something interesting.

arch/parisc/kernel/traps.c::
    void die_if_kernel(char *str, struct pt_regs *regs, long err)
    {
            if (user_mode(regs)) {
                    if (err == 0)
                            return; /* STFU */

                    printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "n",
                            current->comm, current->pid, str, err, regs->iaoq[0]);
    #ifdef PRINT_USER_FAULTS
                    /* XXX for debugging only */
                    show_regs(regs);
    #endif
                    return;
            }

            oops_in_progress = 1;

            /* Amuse the user in a SPARC fashion */
            printk(
    "       ____________________________ n"
    "     < Your System ate a SPARC! Gah! >n”
    ”       ——————————————— n”
    ”             \   ^__^n”
    ”              \  (xx)\_______n”
    ”                 (__)\         )\/\n”
    ”                  U   ||——–w |n”
    ”                      ||     ||n”);

A cow. The output of `printk’ function goes to in-kernel buffer. So you should be able to see this animal using dmesg. It seems parisc maintainer is enjoying the development.

An interesting reference here is the word “SPARC”. Why is it SPARC? Yes Linux does run on SUN SPARC architecture, but what is its relationship here? I dug into SPARC specific source code. It is stored in:

include/asm-parisc
arch/parisc

Digging into arch/sparc/kernel/traps.c:

    void die_if_kernel(char *str, struct pt_regs *regs)
    {
            static int die_counter;
            int count = 0;

            /* Amuse the user. */
            printk(
    "              \|/ ____ \|/n"
    "             \"@'/ ,. \`@\"n"
    "              /_| \__/ |_\n"
    "                 \__U_/n");

A mysterious being! parisc cow must have eaten this guy.

As you can see, parisc maintainer was referring to SPARC-specific code while developing parisc specific code. This maintainer excercised the power of source code. And now, you can inherit the power as well.

By the way, RH236 - Red Hat Linux Kernel Internals and RH442 - Red Hat Enterprise System Monitoring and Performance Tuning training courses introduce you to the other cow (copy-on-write) in kernel code. If you would like to know more about it, we encourage you to take these courses.

About the authors

Masatake Yamato is an RHCE and a Red Hat GPS consultant. Ryoichiro Tsuruno is also an RHCE and a Red Hat Solutions Architect. They both work from the Tokyo office.

5 responses to “Tip from RHCEs: Cows in the Linux kernel”

  1. John Poelstra says:

    Why are you using sudo to install the source rpm and build the kernel? Both are unnecessary and building source as root is bad idea. I would hope this is not considered “RHCE Best Practices” :)

  2. Thorsten Leemhuis says:

    >John Poelstra says:
    > Why are you using sudo to install the source rpm and build
    > the kernel? Both are unnecessary and building source as root
    > is bad idea. I would hope this is not considered “RHCE Best
    > Practices”

    :-)

    In addition to this good comment from John: install rpmdevtools from EPEL and run “rpmdev-setuptree” to create a buildtree ~/rpmbuild and a ~/.rpmmacros file to quickly set up a rpm build environment for a user.

  3. P Shashank BRao says:

    Hi
    I RHEL 4 2.6 but there is no souce code inside it I want the source code how can I get. rpm is present but no source code is there in the /usr/src/redhat…
    Can any body help me ???

  4. gps magazine says:

    gps magazine

    http://sumpit.info

  5. no redeem says:

    A moose once bit my sister.

Leave a reply