Sunday, April 28, 2013

Learning by doing: Compiling your own custom kernel for fun and profit

You know that Linux kernel thing, that has thousands of developers from all over the world, some of which do it professionally, most of which do it for the love of solving problems (or something)?

I look at it as a great chance for learning.

It's Open Source. Get the source code, check out one of the innumerable online tutorials, and give it a shot. That is, if the source isn't available in your distribution of choice (Debian has it, of course) already with all the bells and whistles preselected.

The first time one tries "$ make menuconfig", it's a mind-numbing number of options, drivers, things to be compiled in and things to be built as modules for loading if, and only if, needed.

Taking your distributions pre-configured kernel source, and changing only those few things that you wish to play with, is the best way to jump in. Most distributions compile for the basic x86-686 processor, which will run on most anything the people reading this blog would use. But if you have an AMD, or a newer Intel, customizing to your particular hardware can be a great excuse to play at compiling your own kernel.

Even in a modern car, you and I may not be able to tune them any more, but we can still change the oil and spark plugs for that "this is mine" feeling.

Now it may very well be that only seriously dedicated supercomputer users will notice any difference between the pre-packaged kernel that comes with every distribution and one which is compiled to the particular CPU, memory requirements, minimal drivers, and such. I can honestly say I've never noticed any speed-up.

I first compiled Linux 2.2.19 because my boss at the time wanted his server running with the latest vanilla kernel. (The vanilla kernel is the name given to what is downloaded from, rather than taking what comes with the distribution.)

Then, in 2003 when I owned a Sony Vaio laptop, the wifi card that came in it had one digit out of place. It was custom for Sony in just that way, but it made it so the stock kernel driver didn't recognize it.

During the time it took for the fix to make it into the stock kernel, I edited the driver source code, changed a "2" to a "3", and then built the kernel for myself.

Even today, I have an HP laptop with an nVidia GPU, and there's just something about the Debian kernel, the nVidia driver, and that particular video card, that doesn't quite work right. But it's running a vanilla Linux 3.4.42 right now, and that works just fine.

Except for that one laptop, I just compile kernels for the fun of it.

Merely because I can.

But I meant this to be a post about learning.

Even with all the many thousands of people who compile the vanilla kernels, the distribution packagers, the corporate cattle, and the people like me who are just interested amateurs, there still remains something that troubles me:

Compiler Warnings. Like this:

drivers/isdn/gigaset/capi.c:309:20: warning: ‘format_ie’ defined but not used [-Wunused-function]

There are several dozen such errors, mismatched variables, unused and/or undeclared, cluttering up the output. And these are easy fixes. There's no grand scheme to worry about, no change in logic flow or style, just a declaration where there wasn't one, or the commending out of a variable declaration that isn't used.

Greg Kroah Hartman's wonderful talk on the development cycle of the Linux kernel:

In it, Greg talks about the number of patch submissions by organization and individual, way down to where individual people are submitting one patch (like I did), and he points to a contributor who is sending in spelling fixes.

Wouldn't fixing compiler warnings be a great way to learn what is going on, practice C, or in my case assembler, perhaps in a programming class? Isn't this an excellent real-world example to be used for teaching and learning, even if the changes are never submitted?

Or even better, if they are submitted (after being tested, of course)?

I can say from my own experience that even though I stumbled through my one and only patch submitted to the Linux Kernel Mailing List, I received consideration and assistance from the members of the list in doing it the right way. What more could a student ask for?

To help out compiling your own, here's my recipe:

  1. Download the kernel you want to /usr/src and uncompress it, tar -xf linux-3.8.10.tar.xz
  2. cd /usr/src/linux-3.8.10 
  3. cp /boot/config-whatever-is-latest ./.config
  4. make menuconfig This will give you the horrible list of options seen in the graphic captured above. Don't let that scare you. Browse around, make what changes you want
  5. Even if you change nothing, save when you exit!
The old way of building and installing kernels was with this series of commands, issued in this order, with the install commands being issued as root: 
  1. make
  2. make modules
  3. make install
  4. make modules install
The kernel comes with a very nice trick now, for us Debian users. I say "now" not because it hasn't been there for years, only that I didn't know about it until 2011. It's a very nice perq:
  • $ make -j 2 KDEB_PKGVERSION=1.custom deb-pkg
This uses multiple threads for us multi-core owners, "-j 2", it lets me tack on a package version so that it's distinct from the pre-made kernels, and it builds with this one command a set of ready-to-install packages in /usr/src with no further input:
  • linux-firmware-image_1.custom_i386.deb
  • linux-headers-3.8.10_1.custom_i386.deb
  • linux-image-3.8.10_1.custom_i386.deb
  • linux-libc-dev_1.custom_i386.deb
I just install the image and sometimes header packages, Debian already has the other things covered.

So there you go. Don't fear the command line! Don't fear the kernel! Dive in, try things. Just don't delete the kernel that came installed with your distribution, and the worst thing that could happen is to have to reboot back into that and delete the new one.

And that's not so hard. 

Update: Something I found out that you should know.

Once you're done installing your kernel, and it's working, be sure to to back into the build directory, /usr/src and issue the following command:
  • $ make clean
This deletes all the object files and intermediate steps that were taken prior to building your binary install images. I did a quick du command before and after running make clean and found that it cleared up about 5.9GB of disk space per kernel version.

Deleting the used .deb files is fine too, once you're satisfied that everything is running to your satisfaction. 


  1. I thought I was the only one with a laptop with one digit out of place. It took me awhile to notice this until a friend brought this up. Was your your laptop similar to the Sony vaio svf15414cxb?

    1. It was a 2003 "desktop replacement" power-house laptop, and I've forgotten the exact model number. Seems Sony does this all the time.