Saturday, June 14, 2008

You Really Should Hack Linux

I have a confession to make. I'm an avowed Linux geek, yet I haven't complied the kernel in years. The last time was probably in school when I had to write my own scheduler for the kernel as an assignment, which isn't all that bad when you consider that most people compiling their own kernels are just enabling some obscure driver that they needed. They haven't made Major Modifications to a core piece like The Scheduler. Right? Right? Well, OK, the scheduler wasn't anything to write home about, but it still felt pretty l33t. Anyway, I've decided it's time I delve into the source of Linux again. It's one of the most successful large software projects on the planet, and it's completely open for anyone to dig into. It would be a horribly wasted opportunity for a serious software engineer to miss out on, especially someone interested in nitty-gritty low-level stuff. Even if you aren't interested in OS code or drivers at all, you could study it to learn about tools, coding conventions, documentation techniques, release management processes, debugging techniques, or how to do modularity and configurability, all for a pretty big project. Where else can you get all that for free? Convinced yet? OK then. Off we go.

I'll be using my Ubuntu Hardy Heron machine for development. Conveniently enough, there is a nice little package you can install called linux-kernel-devel which is described thusly:

This is a dummy package that will install all possible packages required to hack comfortably on the kernel.

I don't know about you, but I like to be comfortable when I hack. There is a helpful package included in linux-kernel-devel called kernel-package that makes it easy to create a debian package (.deb) out of our custom kernel, and to do that it's nice to have fakeroot, which allows you to make debian packages without actually being root, so install these two packages like so:

sudo aptitude install linux-kernel-devel fakeroot

It is customary (necessary?) to put your Linux source code in the /usr/src directory. Astute readers will notice that this directory is owned by root, but users in the src group can write there too. To avoid doing too much as root, add yourself to the src group like so:

sudo adduser <username> src

You'll need to log out and log back in (or start a new login shell, or maybe you can simply newgrp src) for the change to take effect. Test that you can create a file in /usr/src with a touch newfile command in that directory. Did it work? Sweet.

Now it's time to download some source code. The kernel is kept under revision control with git. There are other ways to get the source, but if you want the full kernel hacking experience, clone Linus' git repository in /usr/src like so:

git clone git:// linux-2.6

This will probably take a while (I told you this was no toy project!). Once you've done that you can stay up-to-date by running git pull in the linux-2.6 directory.

Before we make a change, let's create our own branch to work off of. In the linux-2.6 directory run

git checkout -b my-cool-branch

Choose a better branch name then that. This will create the branch and make it current. Type git branch to see which branches you have and which one is current. OK, now we can make sure that the kernel will build (a good idea to do before you go making changes to the code). Before you build though, you need to configure your kernel. There are an amazing number of configuration options for the kernel. You can see these by running make xconfig (if it doesn't work, try installing libqt3-headers first, or maybe you only need qt3-dev-tools and libqt3-mt-dev, sorry, I didn't test that very well). Pretty overwhelming at first. An easier thing to try at first is to re-use the configuration for the currently running kernel. On Ubuntu (and Debian) the configurations for installed kernels are found in /boot/config-*. Copy the config for the currently running kernel like this:

cp /boot/config-`uname -r` .config

Then run

make xconfig

to see what is in that configuration and tweak it if desired (I wouldn't yet). Once you are happy with your configuration, save and exit xconfig. Now it's time to start building. Well almost. First make sure we are starting out clean. This is where we start doing everything as "fakeroot," and we use the make-kpkg command instead of make itself (read their man pages for more information). OK, clean:

fakeroot make-kpkg clean

That should have been fairly quick. Now the big command:

fakeroot make-kpkg --revision=1 --append-to-version=mycustomkernel --initrd kernel_image kernel_headers

Time to sit back and watch compiler messages fly by. This will take a while (it took 104 minutes on my kvm ubuntu virtual machine). When it finishes, you will have a nice .deb package of your new kernel and its modules in your /usr/src directory. From anywhere you can now type this to install it:

sudo dpkg -i /usr/src/linux-image-2.6.26-rc5mycustomkernel_1_i386.deb

(Obviously the filename will vary depending on which version you are based off of and what options you fed to make-kpkg for --revision and --append-to-version). Now reboot and see if it runs!

OK, I think that's enough for one blog entry. I cover actually making a change to some kernel code in another entry. I'll just close with a list of good references that I used in getting this done.


No comments: