Link to home
Start Free TrialLog in
Avatar of gabbadar
gabbadar

asked on

Kernel Rebuild Advise

I'm trying to trim my kernel down, the default is pretty bloated. I'm just wondering how anybody else has gone about learning what options are necessary, and which aren't.

I've managed to go through the whole process successfully, but I keep getting a little too ambitious with trimming options out. It seems this is such a trial-and-error process, and their has to be a better way. For example, I can get the low hanging fruit: I know I don't need SCSI drivers, Reiser, or JFS compiled in, and that I need almost the full netfilter suite; but it seems, even though I'm taking out some deprecated code when I reboot the kernel won't load, or I break my PPP connection... Whats more is I don't know how to determine what it was I did wrong. In some cases my machine will reboot perpetually after loading the kernel, and there's no way for me to even read logs to find out what I did wrong.

I guess what I'm asking of an expert in compiling a trim kernel for their system is how you've learned. Are there any recommended books. Did you learn simply by trial, google, and error; or is it just a matter of experience before being able to quickly determine what code is absolutely, no longer necessary, and which is better off being untouched.
SOLUTION
Avatar of http:// thevpn.guru
http:// thevpn.guru
Flag of Denmark image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Duncan Roe
I think your best way to learn is to jump in and do it. What distribution are you starting from? or more in particular what boot loader do you use? I only ever use LILO so can't help you if you use GRUB but I understand it's all documented and easy to use.
Always be sure to build a kernel of a different name from last time - this will create a new modules directory rather than overwriting your existing one (which you really don't want, believe me:)
The linux configuration is encapsulated in a file called ".config" in your linux source directory. I keep this file under RCS control so I can always get back to where I came from (providing I remember to check it in, but you learn to do that).
The kernel name (that I said you should always change) is specified in the top-level Makefile, which I also keep under RCS control.
Of course you can use any revision control system you like for these 2 files - it's just that I think it's important to use something.
You configure and rebuild the kernel and modules using the "make" command. There are lots of different Makefile targets but you'll only need a few of them. No need to trawl through the Makefile to find them these days - "make help" lists all the available targets in functional groups.

Please try "make help" now. My next post will assume you can refer to it.
A WORKED EXAMPLE (sort of)

If you're going to do some configuration work with the kernel, I'd suggest it's best done on the latest. Go to ftp://ftp.kernel.org/pub/linux/kernel/v2.6 and download whatever is the newest one. Today it's linux-2.6.24.1.tar.bz2 for instance.
I keep my downloads in /usr/gz, so after getting linux-2.6.24.1.tar.bz2:

12:00:43$ cd /usr/src
12:01:07$ tar -xjf /usr/gz/linux-2.6.24.1.tar.bz2
12:02:18$ cd linux-2.6.24.1

This is a brand new kernel, so there is no config file:

12:05:34$ ls .config
ls: .config: No such file or directory

Get the config file for the latest kernel

TRICK #1 (RCS-specific)

.config is under RCS control in the previous source directory. How to continue that control to the current one? Answer: make RCS a symbolic link to some central location. I already did that, so now I can link the new source tree to it:

12:05:58$ ln -s ~/rcsdirs/linux_64 RCS

(I have separate directories for 32-bit and 64-bit builds - this one will be 64)

The Makefile will have changed a lot, and we only ever want to change a single early line (actually I think "make config" lets you do that nowadays but I still do it the old way). Look at the changes to the first few lines:

12:17:41$ rcsdiff Makefile |head -8
===================================================================
RCS file: RCS/Makefile,v
retrieving revision 1.26
diff -r1.26 Makefile
3,5c3,5
< SUBLEVEL = 22
< EXTRAVERSION = .9fba
< NAME = Holy Dancing Manatees, Batman!
---
> SUBLEVEL = 24
> EXTRAVERSION = .1
> NAME = Err Metey! A Heury Beelge-a Ret!

The only line we want to change is EXTRAVERSION. You can see from the above that this Makefile was for 2.6.22 by the way. Check in Makefile as_is to avoid accidents later:

12:17:48$ ci -u -m"Vanilla 2.6.24.1" Makefile
RCS/Makefile,v  <--  Makefile
new revision: 1.27; previous revision: 1.26
done

Check out the config. "make config" will take it as a starting point. N.B. I refer to "make config" as a generic for all the config targets. "make config" is actually the original and very tedious interface, we'll use something else:

12:20:52$ co .config
RCS/.config,v  -->  .config
revision 1.26
done

Striclty, we should now run "make mrproper" to clean out everything before reconfiguring. It will remove .config so we'd have to check it out again. If you ever find you want to start from scratch again, make mrproper then co .config. Anyway we won't do that now: we're ready to do the configure. "xconfig" is a GUI target that I use. It relies on a few X llibraries' being installed and may just possibly fail for you. If it does fail, "menuconfig" is an ncurses-based alternative. Both xconfig and menuconfig give you access to configuration help. Let's go"

12:38:59$ make xconfig 2>&1 | tee log_make_menu_config

You can just type "make xconfig" if you want. I keep the log "just in case" I need it (you very rarely do, but I'll show you why you might later in this post).

You should see 3 panels. The left hand one is all the items you can configure. You configure them in the top right panel. The lower right panel displays Help when available. Try clicking a few items to see what happens but don't change anything yet.

I recommend you save and quit now. This will make a .config which is valid for the current kernel version. It will not compare easily to the previous .config, because the order of items shuffles around. I would save this as the baseline for future comparisons:

12:53:34$ ci -u -m"2.6.24 with my 2.6.22 defaults" .config

Have a quick look at the log file (see box). The warnings always happen when using one revision's .config for a new revision, because the way items are configured changes. Because it mentions IDE, I might use it as a hint to be sure to check, when next in the xconfig gui,  how my IDE is configured, just in case it's no longer what I want. If you find something you don't  like, just change it while in the GUI.

You're now ready to run "make xconfig" again and start trimming.
(I have to go on some domestic errands now, will post next part later).
12:52:33$ cat log_make_menu_config
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/docproc
  CHECK   qt
  HOSTCC  scripts/kconfig/conf.o
sed < scripts/kconfig/lkc_proto.h > scripts/kconfig/lkc_defs.h 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
  HOSTCC  scripts/kconfig/kconfig_load.o
  HOSTCC  scripts/kconfig/kxgettext.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/lex.zconf.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
/usr/lib64/qt-3.3.8/bin/moc -i scripts/kconfig/qconf.h -o scripts/kconfig/qconf.moc
  HOSTCXX scripts/kconfig/qconf.o
  HOSTLD  scripts/kconfig/qconf
scripts/kconfig/qconf arch/x86/Kconfig
.config:47:warning: trying to assign nonexistent symbol IPC_NS
.config:53:warning: trying to assign nonexistent symbol UTS_NS
.config:172:warning: trying to assign nonexistent symbol IOMMU
.config:202:warning: trying to assign nonexistent symbol PM_SYSFS_DEPRECATED
.config:451:warning: trying to assign nonexistent symbol BLK_DEV_IDEDMA_FORCED
.config:452:warning: trying to assign nonexistent symbol IDEDMA_ONLYDISK
.config:481:warning: trying to assign nonexistent symbol IDEDMA_IVB
.config:688:warning: trying to assign nonexistent symbol DGRS
.config:749:warning: trying to assign nonexistent symbol USB_USBNET_MII
.config:797:warning: trying to assign nonexistent symbol INPUT_TSDEV
.config:878:warning: trying to assign nonexistent symbol TIPAR
.config:1526:warning: trying to assign nonexistent symbol EDAC_POLL
.config:1622:warning: trying to assign nonexistent symbol RAMFS
#
# configuration written to .config
#

Open in new window

The next thing I think you should try is to make sure you can build a bootable kernel (i.e.make sure you can boot what you built). To that end, I'd suggest you make a kernel without an initial ram disk (initrd). Under General setup, uncheck the box labeled Initial RAM filesystem and RAM disk (initramfs/initrd) support (BLK_DEV_INITRD). Ensure that any modules you need to be present at boot time are compiled into the base kernel (tick in the box instead of dot). For booting off IDE, everything required probably was built in already, but for SCSI or SATA there will be some modules that you have to build in. "lsmod" will show you what modules are in use - those from the initrd will probably show near the end of the list, which is in "most recently added" order.
Make the above changes in the configurator, Save & Quit.

This is the point where you edit the Makefile. On your first pass through, it's not really necessary, but you might as well do it for the practice. Add some distinctive characters to the end of the EXTRAVERSION line (as you can see I added "fba" to the 2.6.22.9 config (which told me I had added Framebuffer console and ALSA sound). For this post, I changed mine to:

EXTRAVERSION = .1_ee_demo

Now "make" will build the kernel and all loadable modules ("make" is equivalent to "make vmlinux;make bzImage;make modules"). This might take a few minutes because you haven't trimmed out the unwanted modules yet (such trimming reduces time to build and size of modules directory but has no effect on performance otherwise). Alternatively do what I do:

make 2>&1 | tee hee

Later you can review the hee file for warnings etc.

All the above can be done as a normal user, but the next few steps require you to be root. First off, install the modules:

15:29:19# make modules_install

This will create a new directory in /lib/modules (ls /lib/modules to verify).
Next, put the kernel image where the bootloader can find it. bzImage is much smaller than vmlinux, so:

15:37:58# cp arch/x86/boot/bzImage /boot/v2.6.24.1_64

You also want to preserve System.map. I'm not aware of a standard way to do this - I always copy it to the modules directory:

15:45:12# cp System.map /lib/modules/2.6.24.1_ee_demo/

Now tell your boot loader about the new kernel (which I now see you already figured out) and try it.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gabbadar
gabbadar

ASKER

Thanks for the replies! I had looked at that book once, but it was a little over my head at the time, I'll have to take a second look.


Duncan, wow, thanks. Everything you've posted so far has been very informative. I've got a few questions about your posts though, if you don't mind.

The first thing I noticed is that you've mentioned using revision control. I do have the 'ci', and 'co' commands available to me (which is all I would need to use RCS, right?), but how would using those be any different than, say, copying my .config file after every successful build to somewhere within the exiting source directory (ex. trim-4.config)? I don't understand the benefits.

Second, you mentioned, and I've also noticed, that .config files throw warnings between kernel revisions, which kind of scared me into starting with a default .config. Is there no way to fix this other than to manually check the logs (which I didn't know before your post), and make sure nothing bad has changed? I can identify the easy stuff: IDE, USB, *FS. But what about the stuff I can't identify, what are the chances of something being broken that I'm just not aware of? DRGS; whats that?

Finally, I'm trying to cut down the kernel just for my own knowledge, but also for security. I'm playing around with an iptables firewall, and had to add some netfilter functions that weren't there by default. And while I was there, I had also read that a kernel built without module support would be slightly more secure because it would make the loading of a rootkit more difficult. Rather than build an enormous kernel where all that was modularized is now static, I wanted to cut it down.

Thanks again, you've been super-helpful!
Thanks for the positive feedback. This is a work morning so I really don't have time to go into all the benefits of RCS right now ;) yes you could rename your configs but you lose the benefits of rcsdiff (you'll have that command too) and the ability to have a separate repository and the way you can put (rcs) comments against your revisions. From your poit of view, it just lets you manage stuff much better. When actually programming there's another big gain over renaming versions: when you grep for a variable you don't get matches in all the old versions - if you program then that's a good reason to get into the habit. Other commands in the RCS suite are "rcs" (useful for changing comments) and rcsmerge (not usually used in conjunction with .config).
Different .config files tend to look hard to compare to start with - the generator tends to insert and remove a lot of comment lines for even the smallest change, so I find the following command useful:

rcsdiff .config|grep -E -v '^([<>] ($|#))|([0-9,]+[adc][0-9,]+$)|(---$)'

Substitute your own diff before the pipe character if you decide to stick with renaming.

Don't worry about the warnings. You only need to check that your config gives you what you want (i.e. while in the GUI, visit all the parts critical to you). The most striking example of that recently (that I know of) was when SATA configuration moved somewhere in the 2.6.teens. I looke in the old place and it wasn't there - so I just had to keep looking until I found it.

If you don't recognize a symbol, chances are it won't affect you. Remember, "make config" always builds a consistent .config (though the rebooting one you built still intrigues me).

Cheers ... Duncan
Ok, well, I'm sold on using the revision system. I've partially taken an online tutorial: http://www.jodypaul.com/SWE/RCSTutorial/RCSTutorial.html

Great stuff, that is. I could certainly use to help keep track of my FW scripts even!