The Linux Kernel HOWTO

Al Dev (Alavoor Vasudevan)


          
        

v7.3, 27 Oct 2003

This is a detailed guide to kernel configuration, compilation, upgrades, and troubleshooting for ix86-based systems. Can be useful for other architectures as well. This document is kept small & simple, so that even non-technical "home computer users" will be able to compile and run the Linux Kernel.


Table of Contents
1. Introduction
1.1. WARNING NOTICE
2. Quick Steps - Kernel Compile
2.1. Precautionary Preparations
2.2. Minor Upgrading of Kernel
2.3. New Release Changes: Documentation
2.4. For the Impatient
2.5. Building New Kernel - Explanation of Steps
2.6. Troubleshooting
2.7. Post Kernel Building
2.8. Where to Report Bugs ?
3. Loadable Modules
3.1. Installing the module utilities
3.2. Modules distributed with the kernel
3.3. Howto Install Just A Single Module ?
4. Cloning of Linux Kernels
5. Important questions and their answers
5.1. What does the kernel do, anyway?
5.2. Why would I want to upgrade my kernel?
5.3. What kind of hardware do the newer kernels support?
5.4. What version of gcc and libc do I need?
5.5. What's a loadable module?
5.6. How much disk space do I need?
5.7. How long does it take?
6. Patching the kernel
6.1. Applying a patch
6.2. If something goes wrong
6.3. Getting rid of the .orig files
6.4. Other patches
7. Tips and tricks
7.1. Redirecting output of the make or patch commands
7.2. Conditional kernel install
7.3. Kernel updates
8. Mount RPMs With FTPFS
8.1. Using the ftpfs
8.2. The ftpfs Commands
9. Linux Kernel Textbooks and Documents
10. Kernel Files Information
10.1. vmlinuz and vmlinux
10.2. Bootloader Files
10.3. Message File
10.4. initrd.img
10.5. bzImage
10.6. module-info
10.7. config
10.8. grub
10.9. System.map
11. Linux System Administration Tools
12. Install, Upgrade at Speed of Light With apt-get (Redhat, Debian, Suse, Mandrake, Others)
12.1. Source Code of 'apt-get'
12.2. The 'rpmfind' Tool
13. Advanced Topics - Linux Boot Process
13.1. References for Boot Process
14. Other Formats of this Document
14.1. Acrobat PDF format
14.2. Convert Linuxdoc to Docbook format
14.3. Convert to MS WinHelp format
14.4. Reading various formats
15. Appendix A - Creating initrd.img file
15.1. Using mkinitrd
15.2. Kernel Docs
15.3. Linuxman Book
16. Appendix B - Sample lilo.conf
16.1. Resources on LILO
16.2. Troubleshooting LILO
16.3. Sample on LILO
17. Appendix C - GRUB Details And A Sample grub.conf
17.1. References on GRUB
17.2. Tips On GRUB
17.3. Sample GRUB Conf File
18. Appendix D - Post Kernel Building
19. Appendix E - Troubleshoot Common Mistakes
19.1. Kernel Compiles OK but make modules fail
19.2. Compiles OK but does not boot
19.3. The System Hangs at LILO
19.4. No init found
19.5. Lot of Compile Errors
19.6. The 'depmod' gives "Unresolved symbol error messages"
19.7. Kernel Does Not Load Module - "Unresolved symbols" Error Messages
19.8. Kernel fails to load a module
19.9. Loadable modules
19.10. See Kernel Documentations
19.11. make clean
19.12. Huge or slow kernels
19.13. The parallel port doesn't work/my printer doesn't work
19.14. Kernel doesn't compile
19.15. New version of the kernel doesn't seem to boot
19.16. You forgot to run LILO, or system doesn't boot at all
19.17. It says `warning: bdflush not running'
19.18. I can't get my IDE/ATAPI CD-ROM drive to work
19.19. It says weird things about obsolete routing requests
19.20. ``Not a compressed kernel Image file''
19.21. Problems with console terminal after upgrade to Linux v1.3.x
19.22. Can't seem to compile things after kernel upgrade
19.23. Increasing limits
19.24. Where To Report Bugs?

1. Introduction

You compile Linux kernel for one of following reasons:

Note: This document is kept small & simple, so that even non-technical "home computer users" will be able to compile and run the Linux Kernel!


1.1. WARNING NOTICE

It is the usual industry practice to have a debug PC box, a test PC box, and a production PC box. Nobody works directly on a production box without experimenting first on debug PC and test PC. This is because the skills of a person varies and every person needs a warm-up exercise before doing the final show. A computer hardware is a very sophisticated technology like "Space Shuttle" and risks are involved as it can fail unexpectedly. Eventhough efforts are made to ensure that this document is upto-date and all commands are pre-tested, it is strongly recommended that you should practice your skills first on a trainer test PC before you do anything to "LIVE" production box. You will sharpen your skills and hone your knowledge first on a test PC running Linux and after everything works, then change the production box with extreme caution. Even if you break the test PC with dangerous commands you will learn by doing mistakes and you can afford breaking the test PC. You will be more confident working first on Test PC. Most companies purchase old PCs for using them as "Trainer Machines". Please understand that there is no warranty or guaranty on this document and you can build your own warranty by checking this document with your test PC or your home PC (low risk environments). (Write your own warranty document and hang it on wall near your computer!!)


2. Quick Steps - Kernel Compile

This section is written by Al Dev (alavoor[AT]yahoo.com) (The latest version of this document is at "http://milkyway.has.it" and "http://www.milkywaygalaxy.freeservers.com" . You may want to check there for changes). Mirror sites are at - http://milkyway.bounceme.net . These sites have lot of linux goodies and tips.

Kernel re-compile is required in order to make the kernel very lean and which will result in FASTER operating system . It is also required to support any new devices.


2.1. Precautionary Preparations

Before you build kernel, it is a good idea to do a backup of the system. If you had not backed up your system recently then you can do it now. You can use commercial backup tools like BRS Backup-Recovery-Software (also in this page you can find open-source/freeware backup tools listed under 'Backup and Restore Utility'). Backup is just a suggestion and it is not mandatory to do backup before building the Linux kernel.


2.2. Minor Upgrading of Kernel

If you had already built the kernel and you want to upgrade to next patch release, then you can simply copy the existing config file and reuse it. (For example you have built kernel 2.4.19 and want to upgrade to 2.4.20).

For minor upgrades : This step may save you time, if you want to reuse the old settings. Whenever you install the kernel, generally you put the config file in /boot. Do not save the .config as .config.save because 'make mrproper' will wipe out all .config* files!! So, you can use the existing version of config file:

	bash# mkdir /usr/src/kernelconfigs 
	bash# cp /usr/src/linux/.config  /usr/src/kernelconfigs/.config.save
	bash# cp /usr/src/linux/.config  /usr/src/linux/configs/.config.save  # ExtraSafe
	bash# cp /boot/config*  /usr/src/linux/configs/  # ExtraSafe
	bash# cp /boot/config-2.4.18-19.8.0  /usr/src/linux/.config
        
Or another method is - you can copy the .config file from your old linux kernel source tree to new kernel tree.

	bash# ls -l /usr/src/lin*  # You can see that /usr/src/linux is a soft link
	bash# cd /usr/src/linux 
	bash# cp ../linux-old-tree/.config .  # Example cp ../linux-2.4.19/.config .
        

or one other method is - you can use "make oldconfig" which default all questions based on the contents of your existing ./.config file.

NOTE: If you do not have lot of disk space in /usr/src then you can unpack the kernel source package on any partition where you have free disk space (like /home). Because kernel compile needs lot of disk space for object files like *.o. For this reason the /usr/src/linux MUST be a soft link pointing to your source directory.

After this, look in the next section to do make and install.


2.3. New Release Changes: Documentation

If you downloaded the new kernel sources, then make sure you read the following files in /usr/src/linux/Documentation

  • Changes: This file lists the minimum requirements and some notes

  • kernel.txt: This file has 'Understanding the Linux Kernel'

  • Read all *.txt files in /usr/src/linux/Documentation but most important ones are kernel*.txt files.


2.4. For the Impatient

  1. Unpack the sources

  2. cd /usr/src/linux; mkdir /usr/src/kernelconfigs ; cp /usr/src/linux/.config /usr/src/kernelconfigs/.config.save; make clean; make mrproper; make clean; cp /usr/src/kernelconfigs/.config.save .config # In case you want to reuse the config file ??

  3. Optional - Copy config file : You can copy the config file from your old linux kernel source tree to new kernel tree (may save time, if you want to reuse the old settings).

  4. make xconfig # Nicer, but limited; only runs in "X"

  5. make dep

  6. Give a unique name to your new Kernel - Edit /usr/src/linux/Makefile and change EXTRAVERSION

  7. nohup make bzImage

  8. 'make modules' and 'make modules_install'

  9. And you can go to lunch or go to bed (have nice Linux dreams in sleep) and when you come back the system is ready! And see the log with 'less nohup.out'.

  10. make install # But "NOT recommended" - use cp /usr/src/linux/arch/i386/boot/bzImage /boot/bzImage.myker

    Copy the System.map file to /boot # cp System*.map* /boot/

    Copy your kernel "configuration file" (the options you selected) Not required but will be useful later. cp .config /boot/config.KERNEL_VERSION.Name

  11. Configure GRUB or LILO.

  12. Reboot and check new kernel is booting

  13. Create emergency boot disk - bzdisk or mkbootdisk

  14. Optional - make rpm # To build rpm packages

  15. Optional - make clean (If you want to free up disk space)

See details of above steps in the following sections....


2.5. Building New Kernel - Explanation of Steps

Details of the steps mentioned in the previous section:

Note: Below 'bash#' denotes the bash prompt, you should type the commands that appear after the 'bash#' prompt. Below are commands tested on Redhat Linux Kernel 2.4.7-10, but it should work for other distributions with very minor changes. It should also work for older kernel versions like 2.2, 2.0 and 1.3. It should also work for future or newer versions of kernel (with little changes - let me know).

  • Note: You can have many kernel images on your system. By following the steps below you do not overwrite or damage your existing kernel. These steps are very safe and your current kernel will be intact and will not be touched.

  1. Unpack the sources: Login in as 'root' throughout all these steps. Mount Redhat linux cdrom (Disc 2 of Redhat9) and install the linux kernel source rpm
    
	bash$ su - root
    	bash# cd /mnt/cdrom/RedHat/RPMS 
    	bash# rpm -i kernel-headers*.rpm 
    	bash# rpm -i kernel-source*.rpm 
    	bash# rpm -i dev86*.rpm   
    	bash# rpm -i bin86*.rpm   
                  
    (The bin86*.rpm and 'as86' is required only for OLDER Linux systems like Redhat 5.x. Get Intel assembler 'as86' command from dev86*.rpm on cdrom or from bin86-mandrake , bin86-kondara ). In latest Redhat 9, the kernel-source.rpm contains the kernel-headers. Usually kernel source is on Redhat discs or in SRPMs disc. Otherwise, you can get from rpmfind.net kernel-source (look for RawHide for latest Redhat) and rpmfind.net kernel-headers . Also make sure that /usr/src/linux is soft link pointing to proper unpacked source.
    
	bash# cd /usr/src
    	bash# ls -l    # You should see that /usr/src/linux is soft link pointing to source
    	lrwxrwxrwx    1 root     root           19 Jan 26 11:01 linux -> linux-2.4.18-19.8.0
    	drwxr-xr-x   17 root     root         4096 Jan 25 21:08 linux-2.4.18-14
    	drwxr-xr-x   17 root     root         4096 Mar 26 12:50 linux-2.4.18-19.8.0
    	drwxr-xr-x    7 root     root         4096 Jan 14 16:32 redhat
                  
    If it is not a soft link then do rename /usr/src/linux to /usr/src/linux-2.4.yy and create a soft link.

    NOTE: If you do not have lot of disk space in /usr/src then you can unpack the kernel source package on any partition where you have free disk space (like /home). Because kernel compile needs lot of disk space for object files like *.o. For this reason the /usr/src/linux MUST be a soft link pointing to your source directory.

  2. Clean : Before doing mrproper below, you may want to backup the .config file.
    
	bash# cd /usr/src/linux 
        bash# mkdir /usr/src/kernelconfigs ;
        bash# cp /usr/src/linux/.config  /usr/src/kernelconfigs/.config.save;
    	bash# cp /usr/src/linux/.config  /usr/src/linux/configs/.config.save  # ExtraSafe
    	bash# cp /boot/config*  /usr/src/linux/configs/  # ExtraSafe
    	bash# make clean
    	bash# make mrproper  # "MUST DO THIS mrproper", otherwise you will face hell lot of problems !!
    	bash# make clean
    	bash# cp /usr/src/kernelconfigs/.config.save .config  # In case you want to reuse the config file ??
                  

  3. Optional - Copy config file : This step may save you time, if you want to reuse the old settings. Whenever you install the kernel, generally you put the config file in /boot. There are some baseline config files which are located in /usr/src/linux/configs/kernel-*.config which you can use. So, you can use the existing version of config file:
    
    bash# mkdir /usr/src/kernelconfigs ;
        bash# cp /usr/src/linux/.config  /usr/src/kernelconfigs/.config.save;
    	bash# cp /usr/src/linux/.config  /usr/src/linux/configs/.config.save  # ExtraSafe
    	bash# cp /boot/config*  /usr/src/linux/configs/  # ExtraSafe
    	bash# cp /boot/config-2.4.18-19.8.0  /usr/src/linux/.config
    	Or copy from the default vanilla config file from /usr/src/linux/configs
    	bash# cp /usr/src/linux/configs/kernel-2.4.18-i686.config  /usr/src/linux/.config
    	Or for athlon processors
    	bash# cp /usr/src/linux/configs/kernel-2.4.18-athlon.config  /usr/src/linux/.config
                  
    Or another method is - you can copy the .config file from your old linux kernel source tree to new kernel tree
    
	bash# ls -l /usr/src/lin*  # You can see that /usr/src/linux is a soft link
    	bash# cd /usr/src/linux 
    	bash# cp ../linux-old-tree/.config .  # Example cp ../linux-2.4.19/.config .
                  
    or one other method is - you can use "make oldconfig" which default all questions based on the contents of your existing ./.config file.

  4. Configure:

    • Start X-windows with 'startx'. If you are not able to start X-window then see next step below.
      
	bash# man startx
      	bash# startx
      	bash# cd /usr/src/linux 
      	bash# make xconfig  # Nicer, but limited; only runs in "X"
                          
      If you get error that wish is not found, then install the tk-8.3.rpm package.

    • If you are not able to start X-window above then try -
      
		bash# export TERM=xterm
      		bash# make menuconfig  # Newer, uses ncurses/curses, may fail if not installed
      	If you find scrambled display, then use different terminal emulators like vt100,
      	vt102, vt220 or ansi. The display will be scrambled and will have garbage 
      	characters in cases where you use telnet to login to remote linux. In such 
      	cases you should use the terminal emulators like vt100, vt220. 
      	For example:
      		bash# export TERM=vt220
      		bash# export TERM=ansi
      	At a lower level of VT, use: 
      		bash# export TERM=vt100
      		bash# make menuconfig  # Newer, uses ncurses/curses, may fail if not installed
      	If the menuconfig command fails then try -
      		bash# make config   # Old, user unfriendly method !!
                          

    The "make xconfig" or "make menuconfig" brings up a user friendly GUI interface. And "make config" brings up command-line console mode interface. You can load the configuration file from /usr/src/linux/.config (dot config file. Note the dot before config). Click on button "Load Configuration from File". Within 'make xconfig' you must do these (to avoid problems) -

    • VERY IMPORTANT !!! : Select proper CPU type - Pentium 3, AMD K6, Cyrix, Pentium 4, Intel 386, DEC Alpha, PowerPC otherwise kernel compile will fail and even if it compiles, it will not boot!!

    • Select SMP support - whether single CPU or multiple CPUs

    • Filesystems - Select Windows95 Vfat, MSDOS, NTFS as part of kernel and not as loadable modules. (My personal preference, but you are free to pick your own option).

    • Enable the Loadable kernel modules support! With this option you can load/unload the device drivers dynamically on running linux system on the fly. See the Modules chapter at Section 3 .

    Save and Exit "make xconfig". All the options which you selected is now saved into configuration file at /usr/src/linux/.config (dot config file).

  5. Dep : And now, do -
    
	bash# make dep
                  

  6. Give a unique name to your new Kernel: You can give a name to your kernel, so that it is unique and does not interfere with others.
    
	bash# cd /usr/src/linux
    	bash# vi Makefile
                  
    Here look for EXTRAVERSION = -19.8.0_Blah_Blah_Blah and change to something like EXTRAVERSION = -19.8.0MyKernel.26Jan2003

  7. Do make: Read the following file (to gain some knowledge about kernel building. Tip: Use the color editor gvim for better readability.
    
	bash# gvim -R   /usr/src/linux/arch/i386/config.in 
    	bash# man less 
    	bash# less   /usr/src/linux/arch/i386/config.in 
    	Type 'h' for help and to navigate press i, j, k, l, h or arrow, page up/down keys. 
                  
    Now, give the make command -
    
		bash# cd /usr/src/linux
    		bash# man nohup
    		bash# nohup make bzImage &  
    		bash# man tail
    		bash# tail -f nohup.out     (.... to monitor the progress) 
    	This will put the kernel in /usr/src/linux/arch/i386/boot/bzImage 
                    

  8. LOADABLE MODULES: Now, while the 'make' is cranking along in the previous step "Do make", you should bring up another new xterm shell window and follow these steps: This step is required ONLY if you had enabled Loadable module support in step "Configure Step" above. Loadable module are located in /lib/modules. You MUST do this step if you enabled or disabled any modules, otherwise you will get 'unresolved symbols' errors during or after kernel boot.
    
	# Bring up a new Xterm shell window and ...
    	bash# cd /usr/src/linux
    	# Redirect outputs such that you do not overwrite the nohup.out which is still running...
    	bash# nohup make modules 1> modules.out 2> modules.err  &
    	bash# make modules_install   # Do this, only after the above make command is successful
                  
    This will copy the modules to /lib/modules directory. See the Modules chapter at Section 3 .

  9. Now go to Lunch or Bed : Since both the make windows are cranking along, and now, you can go to lunch (chitchat, have nap) or go to bed (have nice Linux dreams in sleep) and when you wake up and come back the system is ready! You can check with command 'less nohup.out' to see the log of output.
    
	bash# cd /usr/src/linux
    	bash# less nohup.out
    	bash# less modules.err
    	bash# less modules.out
    	If no errors then do:
    	bash# make modules_install  
                  

  10. bzImage: After bzImage is successful, copy the kernel image to /boot directory. You must copy the new kernel image to /boot directory, otherwise the new kernel MAY NOT boot. You must also copy the config file to /boot area to reflect the kernel image, for documentation purpose.
    
	bash# cp /usr/src/linux/arch/i386/boot/bzImage     /boot/bzImage.myker.26mar2001
    	# You MUST copy the config file to reflect the corresponding kernel image, 
    	# for documentation purpose.
    	bash# cp /usr/src/linux/.config /boot/config-<your_kernelversion_date>
    	# Example: cp /usr/src/linux/.config /boot/config-2.4.18-19.8.0-26mar2001
                  
    NOTE : If you are planning to use the initrd in LILO or GRUB then you may want to build initrd and place it in /boot/initrd*.img. See the Appendix A at Section 15 .

  11. Configure GRUB or LILO : There are two options for boot loading under Redhat Linux - GRUB and LILO. Configure GRUB: GRUB is recent and much better tool than LILO and it is my first preference to use GRUB. LILO is an older technology. GRUB differs from bootloaders such as LILO in that "it can lie to MS Windows and make MS Windows believe that it's installed on the first partition even if it's not!!" . So you can keep your current Linux system where it is and install Windows on the side. See the Section 17 file. Configure LILO: LILO is older tool and see the Section 16 to configure LILO.

  12. Reboot the machine and at lilo press tab key and type 'myker' If it boots then you did a good job! Otherwise at lilo select your old kernel, boot and re-try all over again. Your old kernel is still INTACT and SAFE at say /boot/vmlinuz-2.0.34-0.6

  13. If your new kernel 'myker' boots and works properly, you can create the boot disk. Insert a blank floppy into floppy drive and -
    
	bash# cd /usr/src/linux
    	bash# make bzdisk
    	See also mkbootdisk -
    	bash# rpm -i mkbootdisk*.rpm
    	bash# man mkbootdisk
                  

  14. Build RPMs Optional - You can also build RPM packages of kernel, in case you want to install the new image on several machines.
    
	make rpm   # To build rpm packages
                    

  15. Clean: Optional - make clean (If you want to free up disk space)


2.6. Troubleshooting

Having any problems? See the Section 19 .


2.7. Post Kernel Building

See the Section 18 .


2.8. Where to Report Bugs ?

You tried everything above and you think it seems to be a kernel bug. You may want to report this bug so that it will be fixed. You can see the file /usr/src/linux/REPORTING-BUGS and visit the following site - Reporting Bugs for the Linux Kernel .


3. Loadable Modules

Everyone who used 'Loadable Modules' really "loves" them!! I like the Loadable Modules, they are really cute and they break up a large task into tiny manageable pieces. When you start using them, I can bet that you will fall in love them! Loadable Module is peculiar only to Linux. Linux is the first operating system in the world to introduce the concept of Loadable Module. No other operating system has this concept, but in near future other operating systems may implement this.

Loadable kernel modules can save memory and ease configuration. The scope of modules has grown to include filesystems, ethernet card drivers, tape drivers, printer drivers, and more.

Loadable modules are pieces of kernel code which are not linked (included) directly in the kernel. One compiles them separately, and can insert and remove them into the running kernel at almost any time. Due to its flexibility, this is now the preferred way to code certain kernel features. Many popular device drivers, such as the PCMCIA drivers and the QIC-80/40 tape driver, are loadable modules.

See the Module-HOWTO at "http://www.tldp.org/HOWTO/Module-HOWTO" .

And see these man pages

	bash# rpm -i /mnt/cdrom/Redhat/RPMS/modutils*.rpm
	bash# man lsmod
	bash# man insmod
	bash# man rmmod
	bash# man depmod
	bash# man modprobe
      
For example to load the module /lib/modules/2.4.2-2/kernel/drivers/block/loop.o , you would do :

	bash# man insmod
	bash# modprobe loop
	bash# insmod loop
	bash# lsmod 
      
You can set the PATH which the insmod searches in /etc/modules.conf.


3.1. Installing the module utilities

You can install the Module Utilities RPM with:

	bash# rpm -i /mnt/cdrom/Redhat/RPMS/modutils*.rpm
        

insmod inserts a module into the running kernel. Modules usually have a .o extension; the example driver mentioned above is called drv_hello.o , so to insert this, one would say ` insmod drv_hello.o '. To see the modules that the kernel is currently using, use lsmod . The output looks like this: blah# lsmod Module: #pages: Used by: drv_hello 1 ` drv_hello ' is the name of the module, it uses one page (4k) of memory, and no other kernel modules depend on it at the moment. To remove this module, use ` rmmod drv_hello '. Note that rmmod wants a module name, not a filename; you get this from lsmod 's listing. The other module utilities' purposes are documented in their manual pages.


3.2. Modules distributed with the kernel

As of version 2.0.30, most of everything is available as a loadable modules. To use them, first make sure that you don't configure them into the regular kernel; that is, don't say y to it during ` make config '. Compile a new kernel and reboot with it. Then, cd to /usr/src/linux again, and do a ` make modules '. This compiles all of the modules which you did not specify in the kernel configuration, and places links to them in /usr/src/linux/modules . You can use them straight from that directory or execute ` make modules_install ', which installs them in /lib/modules/x.y.z , where x.y.z is the kernel release.

This can be especially handy with filesystems. You may not use the minix or msdos filesystems frequently. For example, if I encountered an msdos (shudder) floppy, I would insmod /usr/src/linux/modules/msdos.o , and then rmmod msdos when finished. This procedure saves about 50k of RAM in the kernel during normal operation. A small note is in order for the minix filesystem: you should always configure it directly into the kernel for use in ``rescue'' disks.


3.3. Howto Install Just A Single Module ?

Let us assume that you already did 'make modules' and 'make modules_install'. And later you did 'make clean' to free up disk space. And now, you want to change a "C" file in one of the modules and want to rebuild just that module and copy the module file to /lib/modules. How do you do it? And, you do not want to give 'make modules' as that will rebuild everything and will take about 2 to 3 hours!

You can compile just a single module file (say like foo.o) and install it. For this simply edit the Makefile and change the SUBDIRS to add only those directories you are interested.

A good example is - I found that my default kernel did not include the NTFS filesystem support (I did make clean after make modules. Darn and Damn it!). So, I decided to compile the loadable module of NTFS. I did not want to compile the whole set (as it will take me about 2 hours), so I followed the procedure below and compiled just the fs/ntfs and did 'insmod ntfs'. It just took me about 5 minutes!!

Another example: If I am interested in installing only fs/autofs module, then I do the following :

	cd /usr/src/linux
	mv Makefile Makefile.original
	cp Makefile.original Makefile.my
	ln -s Makefile.my Makefile   # Because some files underneath still need "Makefile"
	vi Makefile.my
	# And comment out the line having 'SUBDIRS' and add the 
	# directory you are interested, for example like fs/autofs as below :
		#SUBDIRS	=kernel drivers mm fs net ipc lib abi crypto
		SUBDIRS		=fs/autofs
	# Save the file Makefile.my and give -
	make -f Makefile.my modules
	# This will create module autofs.o
	# Now, copy the module object file to destination /lib/modules
	# DANGER: Do NOT DO THIS - "make -f Makefile.my modules_install" This may
	# clean up other good ones in /lib/modules !! But just copy as below:
	cp autofs.o /lib/modules/2.4.18-19.8.0/kernel/fs/autofs
	  
	# Now, reset everything back to normal
	rm Makefile  # This is a link to Makefile.my
	ln -s Makefile.original Makefile
	  
	# Record your changes to the config file for future use
	# Edit the /usr/src/linux/.config file and set the item as module
	cd /usr/src/linux
    mkdir /usr/src/kernelconfigs ;
    cp /usr/src/linux/.config  /usr/src/kernelconfigs/.config.save;
	cp /usr/src/linux/.config  /usr/src/linux/configs/.config.save  # ExtraSafe
	cp /boot/config*  /usr/src/linux/configs/  # ExtraSafe
	vi /usr/src/linux/.config 
	# And change the config parameter. For example in case of my
	# ntfs module I did CONFIG_NTFS_FS=m  to indicate as module.
        

Learn more about Makefile and make. See the manual for GNU make at

Get familiar with the Makefile which makes the modules. The Makefile has module line like

	modules: $(patsubst %, _mod_%, $(SUBDIRS))
        

The patsubst function has the syntax $(patsubst pattern,replacement,text). It uses the percent symbol ([percnt]) the same way pattern rules do - as a string which matches in both the pattern and the replacement text. It searches the text for whitespace-separated words that match the pattern and substitutes the replacement for them.

This makefile includes shell functions as well as standard make functions. The syntax for a shell function is $(shell command). This returns the output of the shell function (stripping new lines).


4. Cloning of Linux Kernels

You may want to build a Linux kernel on a system and then you may want to mass deploy to many identical hardware PCs. To make it easy to install your newly built kernel on hundreds of other systems, you may want to package it in RPMs (Redhat) or DEB package (Debian) or just tar.gz files.

  1. Build a kernel rpm package with rpmbuild -ba kernel*.spec

  2. Check that the kernel*.rpm generated has all the files in /lib/modules/2.x.x-y directory. Otherwise you may want to tar gzip the directory /lib/modules/2.x.x-y and take it to destination machines.

  3. Check that your kernel package has /boot/initrd-2.x.x-y.img file, otherwise you may want to tar gzip and take it to destination machines.

  4. And other files in /boot which are not in the kernel*.rpm package.


5. Important questions and their answers

5.1. What does the kernel do, anyway?

The Unix kernel acts as a mediator for your programs and your hardware. First, it does (or arranges for) the memory management for all of the running programs (processes), and makes sure that they all get a fair (or unfair, if you please) share of the processor's cycles. In addition, it provides a nice, fairly portable interface for programs to talk to your hardware.

There is certainly more to the kernel's operation than this, but these basic functions are the most important to know.


5.2. Why would I want to upgrade my kernel?

Newer kernels generally offer the ability to talk to more types of hardware (that is, they have more device drivers), they can have better process management, they can run faster than the older versions, they could be more stable than the older versions, and they fix silly bugs in the older versions. Most people upgrade kernels because they want the device drivers and the bug fixes.


5.3. What kind of hardware do the newer kernels support?

See the Hardware-HOWTO . Alternatively, you can look at the ` config.in ' file in the linux source, or just find out when you try ` make config '. This shows you all hardware supported by the standard kernel distribution, but not everything that linux supports; many common device drivers (such as the PCMCIA drivers and some tape drivers) are loadable modules maintained and distributed separately.


5.4. What version of gcc and libc do I need?

Linus recommends a version of gcc in the README file included with the linux source. If you don't have this version, the documentation in the recommended version of gcc should tell you if you need to upgrade your libc. This is not a difficult procedure, but it is important to follow the instructions.


5.5. What's a loadable module?

See the Modules chapter at Section 3 .


5.6. How much disk space do I need?

It depends on your particular system configuration. First, the compressed linux source is nearly 14 megabytes large at version 2.2.9. Many sites keep this even after unpacking. Uncompressed and built with a moderate configuration, it takes up another 67 MB.


5.7. How long does it take?

With newer machines, the compilation takes dramatically less time than older ones; an AMD K6-2/300 with a fast disk can do a 2.2.x kernel in about four minutes. As for old Pentiums, 486s, and 386s, if you plan to compile one, be prepared to wait, possibly hours, days..

If this troubles you, and you happen to have a faster machine around to compile on, you can build on the fast machines (assuming you give it the right parameters, that your ulilities are up-to-date, and so on), and then transfer the kernel image to the slower machine.


6. Patching the kernel

6.1. Applying a patch

Incremental upgrades of the kernel are distributed as patches. For example, if you have Linux v1.1.45, and you notice that there's a ` patch46.gz ' out there for it, it means you can upgrade to version 1.1.46 through application of the patch. You might want to make a backup of the source tree first (` make clean ' and then ` cd /usr/src; tar zcvf old-tree.tar.gz linux ' will make a compressed tar archive for you.).

So, continuing with the example above, let's suppose that you have ` patch46.gz ' in /usr/src . cd to /usr/src and do a ` zcat patch46.gz [verbar] patch -p0 ' (or ` patch -p0 [lt ] patch46 ' if the patch isn't compressed). You'll see things whizz by (or flutter by, if your system is that slow) telling you that it is trying to apply hunks, and whether it succeeds or not. Usually, this action goes by too quickly for you to read, and you're not too sure whether it worked or not, so you might want to use the -s flag to patch , which tells patch to only report error messages (you don't get as much of the ``hey, my computer is actually doing something for a change!'' feeling, but you may prefer this..). To look for parts which might not have gone smoothly, cd to /usr/src/linux and look for files with a .rej extension. Some versions of patch (older versions which may have been compiled with on an inferior filesystem) leave the rejects with a # extension. You can use ` find ' to look for you; find . -name '*.rej' -print prints all files who live in the current directory or any subdirectories with a .rej extension to the standard output.

If everything went right, do a ` make clean ', ` config ', and ` dep ' as described in sections 3 and 4.

There are quite a few options to the patch command. As mentioned above, patch -s will suppress all messages except the errors. If you keep your kernel source in some other place than /usr/src/linux , patch -p1 (in that directory) will patch things cleanly. Other patch options are well-documented in the manual page.


6.2. If something goes wrong

(Note: this section refers mostly to quite old kernels)

The most frequent problem that used to arise was when a patch modified a file called ` config.in ' and it didn't look quite right, because you changed the options to suit your machine. This has been taken care of, but one still might encounter it with an older release. To fix it, look at the config.in.rej file, and see what remains of the original patch. The changes will typically be marked with ` + ' and ` - ' at the beginning of the line. Look at the lines surrounding it, and remember if they were set to ` y ' or ` n '. Now, edit config.in , and change ` y ' to ` n ' and ` n ' to ` y ' when appropriate. Do a patch -p0 < config.in.rej and if it reports that it succeeded (no fails), then you can continue on with a configuration and compilation. The config.in.rej file will remain, but you can get delete it.

If you encounter further problems, you might have installed a patch out of order. If patch says ` previously applied patch detected: Assume -R? ', you are probably trying to apply a patch which is below your current version number; if you answer ` y ', it will attempt to degrade your source, and will most likely fail; thus, you will need to get a whole new source tree (which might not have been such a bad idea in the first place).

To back out (unapply) a patch, use ` patch -R ' on the original patch.

The best thing to do when patches really turn out wrong is to start over again with a clean, out-of-the-box source tree (for example, from one of the linux-x.y.z.tar.gz files), and start again.


6.3. Getting rid of the .orig files

After just a few patches, the .orig files will start to pile up. For example, one 1.1.51 tree I had was once last cleaned out at 1.1.48. Removing the .orig files saved over a half a meg. find . -name '*.orig' -exec rm -f {} ';' will take care of it for you. Versions of patch which use # for rejects use a tilde instead of .orig .

There are better ways to get rid of the .orig files, which depend on GNU xargs : find . -name '*.orig' | xargs rm or the ``quite secure but a little more verbose'' method: find . -name '*.orig' -print0 | xargs --null rm --


6.4. Other patches

There are other patches (I'll call them ``nonstandard'') than the ones Linus distributes. If you apply these, Linus' patches may not work correctly and you'll have to either back them out, fix the source or the patch, install a new source tree, or a combination of the above. This can become very frustrating, so if you do not want to modify the source (with the possibility of a very bad outcome), back out the nonstandard patches before applying Linus', or just install a new tree. Then, you can see if the nonstandard patches still work. If they don't, you are either stuck with an old kernel, playing with the patch or source to get it to work, or waiting (possibly begging) for a new version of the patch to come out.

How common are the patches not in the standard distribution? You will probably hear of them. I used to use the noblink patch for my virtual consoles because I hate blinking cursors (This patch is (or at least was) frequently updated for new kernel releases.). With most newer device drivers being developed as loadable modules, though, the frequecy of ``nonstandard'' patches is decreasing significantly.


7. Tips and tricks

7.1. Redirecting output of the make or patch commands

If you would like logs of what those ` make ' or ` patch ' commands did, you can redirect output to a file. First, find out what shell you're running: ` grep root /etc/passwd ' and look for something like ` /bin/csh '.

If you use sh or bash, (command) 2>&1 | tee (output file) will place a copy of (command) 's output in the file ` (output file) '.

For csh or tcsh, use (command) |& tee (output file)

For rc (Note: you probably do not use rc) it's (command) >[2=1] | tee (output file)


7.2. Conditional kernel install

Other than using floppy disks, there are several methods of testing out a new kernel without touching the old one. Unlike many other Unix flavors, LILO has the ability to boot a kernel from anywhere on the disk (if you have a large (500 MB or above) disk, please read over the LILO documentation on how this may cause problems). So, if you add something similar to image = /usr/src/linux/arch/i386/boot/bzImage label = new_kernel to the end of your LILO configuration file, you can choose to run a newly compiled kernel without touching your old /vmlinuz (after running lilo , of course). The easiest way to tell LILO to boot a new kernel is to press the shift key at bootup time (when it says LILO on the screen, and nothing else), which gives you a prompt. At this point, you can enter ` new_kernel ' to boot the new kernel.

If you wish to keep several different kernel source trees on your system at the same time (this can take up a lot of disk space; be careful), the most common way is to name them /usr/src/linux-x.y.z , where x.y.z is the kernel version. You can then ``select'' a source tree with a symbolic link; for example, ` ln -sf linux-1.2.2 /usr/src/linux ' would make the 1.2.2 tree current. Before creating a symbolic link like this, make certain that the last argument to ln is not a real directory (old symbolic links are fine); the result will not be what you expect.


7.3. Kernel updates

Russell Nelson ( nelson@crynwr.com ) summarizes the changes in new kernel releases. These are short, and you might like to look at them before an upgrade. They are available with anonymous ftp from "ftp://ftp.emlist.com" in pub/kchanges or through the URL "http://www.crynwr.com/kchanges"


8. Mount RPMs With FTPFS

By this time, your kernel is compiled and running ok. You will have the need to access countless number of RPMs which you may need to install in near future. One way is to physically mount the Linux CDROMS, but there are more than 3 Linux cdroms and it is cumbersome to remove and change the Linux cdroms. Hence, here comes the FTPFS.

If you want to automate the installing of RPMs, then consider the 'apt-get' command. The apt-get automatically detects all the dependencies and downloads and installs or upgrades the packages automatically. See the section "Install, Update at Speed of Light" in Section 12

FTP File System is a Linux kernel module, enhancing the VFS with FTP volume mounting capabilities. That is, you can "mount" FTP shared directories in your very personal file system and take advantage of local files ops. It is at "http://lufs.sourceforge.net/lufs" and at "http://ftpfs.sourceforge.net" .


8.1. Using the ftpfs

Download the ftpfs and install it on your system. The ftpfs is installed as a module in /lib/modules/2.4.18-19.8.0/kernel/fs/ftpfs/ftpfs.o. And also the command ftpmount is in /usr/bin/ftpmount. And you can do the following:

Login as root (su - root) and run this script:

	#!/bin/sh -x
	# Use this script to mount ftp redhat cdroms rpms directory disk1,2,3
	# Built rpm by name ftpfs.
	# http://lufs.sourceforge.net/main/projects.html
	# ftpmount --help
	# Try this: ftpmount [user[:pass]@]host_name[:port][/root_dir] mount_point [-o]
	# [-uid=id] [gid=id] [fmask=mask] [dmask=mask]
	#ftpmount anonymous:pass@ftp.kernel.org /mnt/ftpfs
	#mkdir -p /mnt/ftpfs /mnt/ftpfs/updates /mnt/ftpfs/rpms /mnt/ftpfs/contrib
	# Redhat ftp mirror sites - http://www.redhat.com/download/mirror.html
	FTPSITE="csociety-ftp.ecn.purdue.edu"
	USER="anonymous:pass"
	ftpmount $USER@$FTPSITE/pub/redhat/redhat  /mnt/ftpfs/site
	ftpmount $USER@$FTPSITE/pub/redhat/redhat/linux/updates/8.0/en/os  /mnt/ftpfs/updates
	ftpmount $USER@$FTPSITE/pub/redhat/redhat/linux/8.0/en/os/i386/RedHat /mnt/ftpfs/rpms
	ftpmount $USER@$FTPSITE/pub/redhat-contrib /mnt/ftpfs/contrib
        


8.2. The ftpfs Commands

Before you even start thinking about mounting FTP volumes, make sure you have a decent bandwidth or it's gonna suck.


8.2.1. The autofs way - A must try!

If you were wise enough to install the autofs/automount bridge (check out the installation notes) there is a cool way to use ftpfs: just try to access any file/dir on the desired server under /mnt/ftpfs.

	cd /mnt/ftpfs/[user:pass@]ftp_server[:port]
          

Something like cd /mnt/ftpfs/ftp.kernel.org. And guess what? You're there!

Normally you will only use this for anonymous ftp since you don't want your user/pass info to show up in the /mnt/ftpfs/ tree.


8.2.2. The ftpmount way

ftpmount [lsqb ]user[lsqb ]:password]@]hostname[lsqb ]:port ][lsqb ]/root_dir] mount_point [lsqb ]-own] [lsqb ]-uid=id] [lsqb ]-gid=id] [lsqb ]-fmask=mask] [lsqb ]-dmask=mask] [lsqb ]-active]


	The parameters: [defaults]
	    * user: The user to be used for logging on the FTP server. [anonymous]
	    * password: The password for that user. [user@ftpfs.sourceforge.net]
	    * hostname: The FTP server.
	    * port: The port the server is listening on. [21]
	    * root_dir: The directory on the FTP server you want to be mounted. This should be specified without the trailing slash (that is "/home/duru", not "/home/duru/"). [/]
	    * mount_point: The local directory you want to mount the FTP server onto.
	    * own: Flag to force ownership on all remote files. Useful for FTP servers that list user IDs instead of user names.
	    * uid: The local user ID you want to be the owner of the mounted tree.
	    * gid: The local group ID you want to own the mounted tree.
	    * fmask: The numeric mode to be ORed on all mounted files.
	    * dmask: The numeric mode to be ORed on all mounted dirs.
	    * active: Flag to enable active mode for FTP transfers. Useful if you're behind some firewall and cannot connect to random ports.
          

Eg: ftpmount mali@ftp.linuxnet.wox.org /mnt/ftpfs -uid=500 -gid=500 -dmask=555

It is generally a good idea not to provide your password as a parameter, since ftpmount will ask for it.


8.2.3. The mount way

If for some reason you choose not to use ftpmount (you probably installed the kernel patch and are too lazy to install ftpmount too), here's the way to use good-ol mount:

mount -n -t ftpfs none mount_point -o ip=server_ip [lsqb ],user=user_name] [lsqb ],pass=password] [lsqb ],port=server_port] [lsqb ],root= root_dir] [lsqb ],own] [lsqb ],uid=id] [lsqb ],gid=id] [lsqb ],fmode=mask] [lsqb ],dmode=mask] [lsqb ],active]

Please note that you have to provide the server's IP and that the only way to enter a password is in clear. For example, while testing, I used the following command:

mount -n -t ftpfs none /mnt/ftpfs -o ip=127.0.0.1,user=mali,pass=my_pass


8.2.4. Some notes

To unmount the volume, you go like

	umount mount_point
          

The own option (-o for ftpmount) forces ownership by the mounting user on all files. This is useful for accommodating servers with strange user/permissions management (SERVU & stuff).

A few words of wisdom:

  • Use -n mount option! I bet you don't want your user/password information listed in mtab.

  • Don't push it! (pushing it = a dozen processes reading on the mount point)

  • It works best for one process! While concurrent access (under normal circumstances) shouldn't cause any problem, the output is optimized for one process reading (the TCP connection is kept alive). So, if you're gonna watch a movie, you don't want other processes to access the mount point and kill the throughoutput (trust me!).

  • The address in IP format sucks! - Go get ftpmount.


9. Linux Kernel Textbooks and Documents

Check the following books on "The Linux Kernel" at

Presentation of Kernel building process NBLUG Linux Seminars - Kernel Building Presentation Talks

Refer also to other relevant HOWTOs at:


10. Kernel Files Information

This section gives a "very brief" and "introduction" to some of the Linux Kernel System. If you have time you can give one reading.

Caution: You should be extra careful about these Kernel Files and you must not edit or touch or move/delete/rename them.


10.1. vmlinuz and vmlinux

The "vm" stands for "Virtual Memory". Linux supports virtual memory unlike old operating systems like DOS which have a hard limit of 640KB memory. Linux can use the hard disk space as "virtual memory" and hence the name "vm". The vmlinuz is the Linux kernel executable. This is located at /boot/vmlinuz. This can be a soft link to something like /boot/vmlinuz-2.4.18-19.8.0. The vmlinuz is created by "make zImage" and you do "cp /usr/src/linux/arch/i386/linux/boot/zImage /boot/vmlinuz". The vmlinuz is a compressed file of vmlinux. The zImage is there for backward compatibility (smaller kernels). Note that, in near future zImage may be dropped in favor of 'make bzImage' (big zImage). The zImage (vmlinuz) is not just a compressed image, but has gzip decompressor code built into it as well (at the beginning). So you cannot use gunzip or gzip -dc to unpack vmlinuz.

Both zImage and bzImage are compressed with gzip. The kernel includes a mini-gunzip to uncompress the kernel and boot into it. The difference is that the old zImage uncompresses the kernel into low memory (the first 640k), and bzImage uncompresses the kernel into high memory (over 1M).

The vmlinux is the uncompressed built kernel, vmlinuz is the compressed one, that has been made bootable. (Note both names vmlinux and vmlinuz look same except for last letter z). Generally, you don't need to worry about vmlinux, it is just an intermediate step.

The kernel usually makes a bzImage, and stores it in arch/i386/boot, and it is up to the user to copy it to /boot and configure GRUB or LILO.


10.2. Bootloader Files

The .b files are "bootloader" files. they are part of the dance required to get a kernel into memory to begin with. You should NOT touch them.

	ls -l /boot/*.b
	-rw-r--r--    1 root     root         5824 Sep  5  2002 /boot/boot.b
	-rw-r--r--    1 root     root          612 Sep  5  2002 /boot/chain.b
	-rw-r--r--    1 root     root          640 Sep  5  2002 /boot/os2_d.b
        


10.3. Message File

The 'message' file contains the message your bootloader will display, prompting you to choose an OS. So DO NOT touch it.

	ls -l /boot/message*
	-rw-r--r--    1 root     root        23108 Sep  6  2002 /boot/message
	-rw-r--r--    1 root     root        21282 Sep  6  2002 /boot/message.ja
        


10.4. initrd.img

See the Appendix A at Section 15 .


10.5. bzImage

The bzImage is the compressed kernel image created with command 'make bzImage' during kernel compile. It important to note that bzImage is not compressed with bzip2 !! The name bz in bzImage is misleading!! It stands for "Big Zimage". The "b" in bzImage is "big". Both zImage and bzImage are compressed with gzip. The kernel includes a mini-gunzip to uncompress the kernel and boot into it. The difference is that the old zImage uncompresses the kernel into low memory (the first 640k), and bzImage uncompresses the kernel into high memory (over 1M). The only problem is that there are a very few machines where bzImage is known to have problems (because the machines are buggy). The bzImage actually boots faster, but other than that, there's no difference in the way the system *runs*. The rule is that if all drivers cannot fit into the zImage, then you need to modularize more.

If the kernel is small, it will work as both a zImage and a bzImage, and the booted system runs the same way. A big kernel will work as a bzImage, but not as a zImage. Both bootimages are gzipped, (bzImage is not bzipped as the name would suggest), but are put together and loaded differently, that allows the kernel to load in higher address space, that does not limit it to lower memory in the pathetic intel architecture. So why have both? Backward compatability. Some older lilos and loadlins don't handle the bzImage format. Note, they *boot* differently, but *run* the same. There is a lot of misinformation given out about what a bzImage file is (mostly about it being bzip2ed).


10.6. module-info

This file "module-info" is a symbolic link:

	$ uname -r
	2.4.18-19.8.0custom
	  
	# ls -l /boot/module-info*
	lrwxrwxrwx    1 root     root           25 Jan 26 10:44 /boot/module-info ->
 module-info-2.4.18-19.8.0
	-rw-r--r--    1 root     root        15436 Sep  4  2002 /boot/module-info-2.4.18-14
	-rw-r--r--    1 root     root        15436 Jan 26 01:29 /boot/module-info-2.4.18-19.8.0
        

Note above that it is not a requirement is make module-info symlink to a kernel specific file like the way System-map and vmlinuz is required. It's just a text file so as long as module-info list is recent, you'll be fine. Before removing all the stock RH kernels from your system, you should make a backup of this file:

# cp /boot/module-info-2.4.20-19.9 /boot/module-info-2.4.20-19.9.backup 
        
It should be safe to do this as module-info rarely changes within the same point release of RH kernels.

This file 'module-info' is created by anaconda/utils/modlist (specific to Redhat Linux Anaconda installer). Other Linux distributions may be having equivalent command. Refer to your Linux distributor's manual pages.

See this script and search for "module-info" updmodules .

Below is a cut from this script:

	#!/bin/bash
	# updmodules.sh
		MODLIST=$PWD/../anaconda/utils/modlist
		MODINFO=$KERNELROOT/boot/module-info-$version
	-- snip cut 
	blah blah blah 
	-- snip cut 
	    # create the module-info file
	    $MODLIST --modinfo-file $MODINFO --ignore-missing --modinfo \
			$(ls *.o | sed 's/\.o$//') > ../modinfo
        

The program anaconda/utils/modlist is located in anaconda-runtime*.rpm on the Redhat CDROM

	cd /mnt/cdrom/RedHat/RPMS
	rpm -i anaconda-8.0-4.i386.rpm
	rpm -i anaconda-runtime-8.0-4.i386.rpm
	ls -l /usr/lib/anaconda-runtime/modlist
        
Get the source code for anaconda/utils/modlist.c from anaconda*.src.rpm at "http://www.rpmfind.net/linux/rpm2html/search.php?query=anaconda" Read online at modlist.c . .

The file 'module-info' is generated during the compile. It is an information file that is at least used during filing proper kernel OOPS reports. It is a list of the module entry points. It may also be used by depmod in building the tables that are used by insmod and its kith and kin. This includes dependancy information for other modules needed to be loaded before any other given module, etc.

Bottom line is: "Don't remove this file module-info."

Some points about module-info:

  • Is provided by the kernel rpms (built by anaconda-runtime*.rpm)

  • Is a link to module-info-{kernel-version}

  • Contains information about all available modules (at least those included in the default kernel config.)

  • Important to anaconda - in anaconda/utils/modlist command.

  • Might be used by kudzu to determine default parameters for modules when it creates entries in /etc/modules.conf. If you move module-info out of the way, shut down, install a new network card, and re-boot then kudzu would complain loudly. Look at the kudzu source code.


10.7. config

Everytime you compile and install the kernel image in /boot, you should also copy the corresponding config file to /boot area, for documentation and future reference. Do NOT touch or edit these files!!

	ls -l /boot/config-*
	-rw-r--r--    1 root     root        42111 Sep  4  2002 /boot/config-2.4.18-14
	-rw-r--r--    1 root     root        42328 Jan 26 01:29 /boot/config-2.4.18-19.8.0
	-rw-r--r--    1 root     root        51426 Jan 25 22:21 /boot/config-2.4.18-19.8.0BOOT
	-rw-r--r--    1 root     root        52328 Jan 28 03:22 /boot/config-2.4.18-19.8.0-26mar2003
        


10.8. grub

If you are using GRUB, then there will be 'grub' directory.

	ls /boot/grub
	device.map     ffs_stage1_5  menu.lst        reiserfs_stage1_5  stage2
	e2fs_stage1_5  grub.conf     minix_stage1_5  splash.xpm.gz      vstafs_stage1_5
	fat_stage1_5   jfs_stage1_5  stage1          xfs_stage1_5
        
See also Section 17 file.


10.9. System.map

System.map is a "phone directory" list of function in a particular build of a kernel. It is typically a symlink to the System.map of the currently running kernel. If you use the wrong (or no) System.map, debugging crashes is harder, but has no other effects. Without System.map, you may face minor annoyance messages.

Do NOT touch the System.map files.

	ls -ld /boot/System.map*
	lrwxrwxrwx    1 root     root           30 Jan 26 19:26 /boot/System.map -> System.map-2.4.18-19.8.0custom
	-rw-r--r--    1 root     root       501166 Sep  4  2002 /boot/System.map-2.4.18-14
	-rw-r--r--    1 root     root       510786 Jan 26 01:29 /boot/System.map-2.4.18-19.8.0
	-rw-r--r--    1 root     root       331213 Jan 25 22:21 /boot/System.map-2.4.18-19.8.0BOOT
	-rw-r--r--    1 root     root       503246 Jan 26 19:26 /boot/System.map-2.4.18-19.8.0custom
        

How The Kernel Symbol Table Is Created ? System.map is produced by 'nm vmlinux' and irrelevant or uninteresting symbols are grepped out, When you compile the kernel, this file 'System.map' is created at /usr/src/linux/System.map. Something like below:

	nm /boot/vmlinux-2.4.18-19.8.0 > System.map
	# Below is the line from /usr/src/linux/Makefile 
	nm vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
	cp /usr/src/linux/System.map /boot/System.map-2.4.18-14   # For v2.4.18
        

From "http://www.dirac.org/linux/systemmap.html"


10.9.1. System.map

There seems to be a dearth of information about the System.map file. It's really nothing mysterious, and in the scheme of things, it's really not that important. But a lack of documentation makes it shady. It's like an earlobe; we all have one, but nobody really knows why. This is a little web page I cooked up that explains the why.

Note, I'm not out to be 100[percnt] correct. For instance, it's possible for a system to not have /proc filesystem support, but most systems do. I'm going to assume you "go with the flow" and have a fairly typical system.

Some of the stuff on oopses comes from Alessandro Rubini's "Linux Device Drivers" which is where I learned most of what I know about kernel programming.


10.9.2. What Are Symbols?

In the context of programming, a symbol is the building block of a program: it is a variable name or a function name. It should be of no surprise that the kernel has symbols, just like the programs you write. The difference is, of course, that the kernel is a very complicated piece of coding and has many, many global symbols.


10.9.3. What Is The Kernel Symbol Table?

The kernel doesn't use symbol names. It's much happier knowing a variable or function name by the variable or function's address. Rather than using size_t BytesRead, the kernel prefers to refer to this variable as (for example) c0343f20.

Humans, on the other hand, do not appreciate names like c0343f20. We prefer to use something like size_t BytesRead. Normally, this doesn't present much of a problem. The kernel is mainly written in C, so the compiler/linker allows us to use symbol names when we code and allows the kernel to use addresses when it runs. Everyone is happy.

There are situations, however, where we need to know the address of a symbol (or the symbol for an address). This is done by a symbol table, and is very similar to how gdb can give you the function name from a address (or an address from a function name). A symbol table is a listing of all symbols along with their address. Here is an example of a symbol table:


	   c03441a0 B dmi_broken
	   c03441a4 B is_sony_vaio_laptop
	   c03441c0 b dmi_ident
	   c0344200 b pci_bios_present
	   c0344204 b pirq_table
	   c0344208 b pirq_router
	   c034420c b pirq_router_dev
	   c0344220 b ascii_buffer
	   c0344224 b ascii_buf_bytes
          

You can see that the variable named dmi_broken is at the kernel address c03441a0.


10.9.4. What Is The System.map File?

There are 2 files that are used as a symbol table:

  1. /proc/ksyms

  2. System.map

There. You now know what the System.map file is.

Every time you compile a new kernel, the addresses of various symbol names are bound to change.

/proc/ksyms is a "proc file" and is created on the fly when a kernel boots up. Actually, it's not really a file; it's simply a representation of kernel data which is given the illusion of being a disk file. If you don't believe me, try finding the filesize of /proc/ksyms. Therefore, it will always be correct for the kernel that is currently running..

However, System.map is an actual file on your filesystem. When you compile a new kernel, your old System.map has wrong symbol information. A new System.map is generated with each kernel compile and you need to replace the old copy with your new copy.


10.9.5. What Is An Oops?

What is the most common bug in your homebrewed programs? The segfault. Good ol' signal 11.

What is the most common bug in the Linux kernel? The segfault. Except here, the notion of a segfault is much more complicated and can be, as you can imagine, much more serious. When the kernel dereferences an invalid pointer, it's not called a segfault -- it's called an "oops". An oops indicates a kernel bug and should always be reported and fixed.

Note that an oops is not the same thing as a segfault. Your program cannot recover from a segfault. The kernel doesn't necessarily have to be in an unstable state when an oops occurs. The Linux kernel is very robust; the oops may just kill the current process and leave the rest of the kernel in a good, solid state.

An oops is not a kernel panic. In a panic, the kernel cannot continue; the system grinds to a halt and must be restarted. An oops may cause a panic if a vital part of the system is destroyed. An oops in a device driver, for example, will almost never cause a panic.

When an oops occurs, the system will print out information that is relevent to debugging the problem, like the contents of all the CPU registers, and the location of page descriptor tables. In particular, the contents of the EIP (instruction pointer) is printed. Like this:

	   EIP: 0010:[<00000000>]
	   Call Trace: [<c010b860>]
          


10.9.6. What Does An Oops Have To Do With System.map?

You can agree that the information given in EIP and Call Trace is not very informative. But more importantly, it's really not informative to a kernel developer either. Since a symbol doesn't have a fixed address, c010b860 can point anywhere.

To help us use this cryptic oops output, Linux uses a daemon called klogd, the kernel logging daemon. klogd intercepts kernel oopses and logs them with syslogd, changing some of the useless information like c010b860 with information that humans can use. In other words, klogd is a kernel message logger which can perform name-address resolution. Once klogd tranforms the kernel message, it uses whatever logger is in place to log system wide messages, usually syslogd.

To perform name-address resolution, klogd uses System.map. Now you know what an oops has to do with System.map.

Fine print: There are actually two types of address resolution are performed by klogd.

  • Static translation, which uses the System.map file.

  • Dynamic translation which is used with loadable modules, doesn't use

System.map and is therefore not relevant to this discussion, but I'll describe it briefly anyhow.

Klogd Dynamic Translation

Suppose you load a kernel module which generates an oops. An oops message is generated, and klogd intercepts it. It is found that the oops occured at d00cf810. Since this address belongs to a dynamically loaded module, it has no entry in the System.map file. klogd will search for it, find nothing, and conclude that a loadable module must have generated the oops. klogd then queries the kernel for symbols that were exported by loadable modules. Even if the module author didn't export his symbols, at the very least, klogd will know what module generated the oops, which is better than knowing nothing about the oops at all.

There's other software that uses System.map, and I'll get into that shortly.


10.9.7. Where Should System.map Be Located?

System.map should be located wherever the software that uses it looks for it. That being said, let me talk about where klogd looks for it. Upon bootup, if klogd isn't given the location of System.map as an argument, it will look for System.map in 3 places, in the following order:

  1. /boot/System.map

  2. /System.map

  3. /usr/src/linux/System.map

System.map also has versioning information, and klogd intelligently searches for the correct map file. For instance, suppose you're running kernel 2.4.18 and the associated map file is /boot/System.map. You now compile a new kernel 2.5.1 in the tree /usr/src/linux. During the compiling process, the file /usr/src/linux/System.map is created. When you boot your new kernel, klogd will first look at /boot/System.map, determine it's not the correct map file for the booting kernel, then look at /usr/src/linux/System.map, determine that it is the correct map file for the booting kernel and start reading the symbols.

A few nota bene's:

  • Somewhere during the 2.5.x series, the Linux kernel started to untar into linux-version, rather than just linux (show of hands -- how many people have been waiting for this to happen?). I don't know if klogd has been modified to search in /usr/src/linux-version/System.map yet. TODO: Look at the klogd srouce. If someone beats me to it, please email me and let me know if klogd has been modified to look in the new directory name for the linux source code.

  • The man page doesn't tell the whole the story. Look at this:


	   # strace -f /sbin/klogd | grep 'System.map'
	   31208 open("/boot/System.map-2.4.18", O_RDONLY|O_LARGEFILE) = 2
          

Apparently, not only does klogd look for the correct version of the map in the 3 klogd search directories, but klogd also knows to look for the name "System.map" followed by "-kernelversion", like System.map-2.4.18. This is undocumented feature of klogd.

A few drivers will need System.map to resolve symbols (since they're linked against the kernel headers instead of, say, glibc). They will not work correctly without the System.map created for the particular kernel you're currently running. This is NOT the same thing as a module not loading because of a kernel version mismatch. That has to do with the kernel version, not the kernel symbol table which changes between kernels of the same version!


10.9.8. What else uses the System.map

Don't think that System.map is only useful for kernel oopses. Although the kernel itself doesn't really use System.map, other programs such as klogd, lsof,


	   satan# strace lsof 2>&1 1> /dev/null | grep System
	   readlink("/proc/22711/fd/4", "/boot/System.map-2.4.18", 4095) = 23
          

and ps :


	   satan# strace ps 2>&1 1> /dev/null | grep System
	   open("/boot/System.map-2.4.18", O_RDONLY|O_NONBLOCK|O_NOCTTY) = 6
          

and many other pieces of software like dosemu require a correct System.map.


10.9.9. What Happens If I Don't Have A Healthy System.map?

Suppose you have multiple kernels on the same machine. You need a separate System.map files for each kernel! If boot a kernel that doesn't have a System.map file, you'll periodically see a message like: System.map does not match actual kernel Not a fatal error, but can be annoying to see everytime you do a ps ax. Some software, like dosemu, may not work correctly (although I don't know of anything off the top of my head). Lastly, your klogd or ksymoops output will not be reliable in case of a kernel oops. See the manual pages by giving commands 'man ksymoops' and 'man klogd'.


10.9.10. How Do I Remedy The Above Situation?

The solution is to keep all your System.map files in /boot and rename them with the kernel version. Suppose you have multiple kernels like:

  • /boot/vmlinuz-2.2.14

  • /boot/vmlinuz-2.2.13

Then just rename your map files according to the kernel version and put them in /boot, like:

	   /boot/System.map-2.2.14
	   /boot/System.map-2.2.13
          

Now what if you have two copies of the same kernel? Like:

  • /boot/vmlinuz-2.2.14

  • /boot/vmlinuz-2.2.14.nosound

The best answer would be if all software looked for the following files:

	   /boot/System.map-2.2.14
	   /boot/System.map-2.2.14.nosound
          

You can also use symlinks:

	   System.map-2.2.14
	   System.map-2.2.14.sound
	   ln -s System.map-2.2.14.sound System.map     # Here System.map -> System.map-2.2.14.sound
          


11. Linux System Administration Tools

There are two best admin tools for Linux. They are Linuxconf and Webmin.

The Linux System administration tools are :

List of User Guides for Linux System Administration:

System Administration Magazine:

Educational courses on Linux System Administration:


12. Install, Upgrade at Speed of Light With apt-get (Redhat, Debian, Suse, Mandrake, Others)

You can automate the process of maintaining the Linux system with the powerful tool like apt-get. The apt-get tool is immensely powerful and used by millions of computers world-wide on Linux systems. The apt-get utility works with Redhat Linux and Debian. The apt-get works with distros which support RPM or Deb packages. The apt-get may work with most of the distributions; if it does not you can very easily tailor the code. Mandrake has tool called urpmi.