by Kamran Husain and Tim Parker
IN THIS CHAPTER
This chapter will look at
Usually, you will want to leave the kernel alone, except when you are performing a major upgrade or installing a new device driver that has special kernel modifications. The details of the process are usually supplied with the software. However, this chapter gives you a good idea of the general process.
Few people will want to change the details in the kernel source code, because they lack the knowledge to do so (or have enough knowledge to know that hacking the kernel can severely damage the system). However, most users will want to install new versions of Linux, add patches, or modify the kernel's behavior a little.
Several versions of Linux are commonly used, with a few inconsistencies between them. For that reason, the exact instructions given here may not work with your version of Linux. However, the general approach is the same, and only the directory or utility names may be different. Most versions of Linux supply documentation that lists the recompilation process and the locations of the source code and compiled programs.
Before you do anything with the kernel or utilities, make sure you have a good set of emergency boot disks, and preferably a complete backup on tape or diskette. Although the process of modifying the kernel is not difficult, every now and then it does cause problems that can leave you stranded without a working system. Boot disks are the best way to recover, so make at least one extra set.
Linux is a dynamic operating system. New releases of the kernel, or parts of the operating system that can be linked into the kernel, are made available at regular intervals to users. Whether or not you want to upgrade to the new releases is up to you and usually depends on the features or bug fixes that the new release offers. You will probably have to recompile and relink the kernel when new software is added, unless it is loaded as a utility or device driver.
Another problem with constant upgrades is that the frequency with which new releases are made available is so high that you can probably spend more time simply loading and recompiling kernels and utilities than actually using the system. This becomes tiresome after a while. Because most major releases of the Linux operating system are available, the number of changes to the system is usually quite small. Therefore, you should read the release notes carefully to ensure that the release is worth the installation time and trouble.
The best advice is to upgrade only once or twice a year, and only when there is a new feature or enhancement to your system that will make a significant difference in the way you use Linux. It's tempting to always have the latest and newest version of the operating system, but there is a lot to be said for having a stable, functioning operating system, too.
If you do upgrade to a new release, bear in mind that you don't have to upgrade everything. The last few Linux releases have changed only about 5 percent of the operating system with each new major package upgrade. Instead of replacing the entire system, just install those parts that will have a definite effect, such as the kernel, compilers and their libraries, and frequently used utilities. This saves time and reconfiguration.
Upgrading, replacing, or adding new code to the kernel is usually a simple process: You obtain the source for the kernel, make any configuration changes, compile it, and then place it in the proper location on the file system to run the system properly. The process is often automated for you by a shell script or installation program, and some upgrades are completely automated--you don't need to do anything except start the upgrade utility.
Kernel sources for new releases of Linux are available from CD-ROM distributions, FTP sites (see Appendix A, "FTP Sites and Newsgroups"), user groups, and many other locations. Most kernel versions are numbered with a version and a patch level, so you will see kernel names such as 1.12.123, where 1 is the major release, 12 is the minor version release, and 123 is the patch number. Most sites of kernel source code maintain several versions simultaneously, so check through the source directories for the latest version of the kernel.
Patch releases are sometimes numbered differently and do not require the entire source of the kernel to install. They require just the source of the patch. In most cases, the patch overlays a section of existing source code and a simple recompilation is all that's necessary to install the patch. Patches are released quite frequently.
Most kernel source programs are maintained as a gzipped tar file. Unpack the files into a subdirectory called /usr/src, which is where most of the source code is kept for Linux. Some versions of Linux keep other directories for the kernel source, so you may want to check any documentation supplied with the system or look for a README file in the /usr/src directory for more instructions.
Often, unpacking the gzipped tar file in /usr/src creates a subdirectory called /usr/src/linux, which can overwrite your last version of the kernel source. Before starting the unpacking process, rename or copy any existing /usr/src/linux (or whatever name is used with the new kernel) so you have a backup version in case of problems.
After the kernel source has been unpacked, you need to create two symbolic links to the /usr/include directory, if they are not created already or set by the installation procedure. Usually, the link commands required are
ln -sf /usr/src/linux/include/linux /usr/include/linux ln -sf /usr/src/linux/include/asm /usr/include/asm
If the directory names shown are different from your version of Linux, substitute the new directory names for /usr/src/linux. Without these links, the upgrade or installation of a new kernel cannot proceed.
After the source code has been ungzipped and untarred and the links have been established, the compilation process can begin. You must have a version of gcc or g++ (the GNU C and C++ compilers) or some other compatible compiler available for the compilation. You may have to check with the source code documentation to make sure you have the correct versions of the compilers, because occasionally new kernel features are added that are not supported by older versions of gcc or g++.
Check the file /usr/src/linux/Makefile (or whatever path the Makefile is in with your source distribution). There will be a line in the file that defines the ROOT_DEV, which is the device that is used as the root file system when Linux boots. Usually the line looks like this:
ROOT_DEV = CURRENT
If you have any other value, make sure it is correct for your file system configuration. If the Makefile has no value, set it as shown in the preceding code line.
The compilation process begins when you change to the /usr/src/linux directory and issue the following command:
make config
This command invokes the make utility for the C compiler. The process may be slightly different for some versions of Linux, so you should check with any release or installation notes supplied with the source code.
The config program issues a series of questions and prompts that you need to answer to indicate any configuration issues that need to be completed before the actual compilation begins. These may be about the type of disk drive you are using, the CPU, any partitions, or other devices, such as CD-ROMs. Answer the questions as well as you can. If you are unsure, choose the default values or the choice that makes the most sense. The worst case is that you might have to redo the process if the system doesn't run properly. (You do have an emergency boot disk ready, don't you?)
Next, you have to set all the source dependencies. This is a step that is commonly skipped, and it can cause several problems if it is not performed for each software release. Issue the following command:
make dep
If the software you are installing does not have a dep file, check with the release or installation notes to ensure that the dependencies are correctly handled by the other steps.
After that, you can finally compile the new kernel. The command to start the process is
make zImage make zdisk make zlilo
This compiles the source code and leaves the new kernel image file in the current directory (usually /usr/src/linux). If you want to create a compressed kernel image, you can use the command
make zImage
Not all releases or upgrades to the kernel support compressed image compilation.
The last step in the process is to copy the new kernel image file to the boot device or a boot floppy. Use the following command to place the file on a floppy:
cp Image /dev/fd0
Use a different device driver, if necessary, to place it somewhere else on the hard drive file system. Alternatively, if you plan to use LILO to boot the operating system, you can install the new kernel by running a setup program or the utility /usr/lilo/lilo. (See Chapter 4, "Booting Linux.")
Now all that remains is to reboot the system and see if the new kernel loads properly. If there are any problems, boot from a floppy, restore the old kernel, and start the process again. Check the documentation supplied with the release source code for any information about problems you may encounter or steps that may have been added to the process.
You may want to link in new device drivers or special software to the kernel without going through the upgrade process of the kernel itself. This is often necessary when you add a new device to the system (such as a multiport board or an optical drive) that should be loaded during the boot process. Alternatively, you may be adding special security software that must be linked into the kernel.
The add-in kernel software usually has installation instructions provided, but the general process is to locate the source in a directory that can be found by the kernel recompilation process (such as the /usr/src directory). To instruct the make utility to add the new code to the kernel, you often need to modify the Makefile. These modifications may be performed manually or by an installation script. Some software has its own Makefile supplied for this reason.
Then, it's time to begin the kernel recompilation with the new software added into the load. The process is the same as shown in the preceding section; the kernel is installed in the boot location or is set by LILO. Typically, the entire process takes about 10 minutes and is quite trouble-free, unless the vendor of the kernel modification did a sloppy job. Make sure that the source code provided for the modification will work with your version of the Linux kernel by reading any text files that accompany the code as well as the software compatibility files included with most distributions of Linux.
Most of the software on a Linux system is set to use shared libraries (a set of subroutines used by many programs). When you see the message
Incompatible library version
displayed after you have performed an upgrade to the system and you try to execute a utility, it means that the libraries have been updated and need to be recompiled. Most libraries are backward-compatible, so existing software should work properly even after a library upgrade.
Library upgrades occur less frequently than kernel upgrades, and you can find them in the same places. There are usually documents that guide you to the latest version of a library, or there may be a file explaining which libraries are necessary with new versions of the operating system kernel.
Most library upgrades are gzipped tar files, and the process for unpacking them is the same as for kernel source code--except that the target directories are usually /lib, /usr/lib, and /usr/include. Usually, any files that have the extension .a or .aa belong in the /usr/lib directory. Shared library image files, which have the format libc.so.version, are installed into /lib.
You may have to change symbolic links within the file system to point to the latest version of the library. For example, if you are running library version libc.so.4.4.1 and upgrade to libc.so.4.4.2, you must alter the symbolic link set in /lib to this file. The command is
ln -sf /lib/libc/so/4/4/1 /lib/libc.so.4
where the last filename in the link command is the name of the current library file in /lib. Your library name may be different, so check the directory and release or installation notes first.
You would also need to change the symbolic link for the file libm.so.version in the same manner. Do not delete the symbolic links because all programs that depend on the shared library (including ls) would be unable to function without them.
You will need to look at the source code if you want to make enhancements to the kernel. The Linux source code can be found in the /usr/src/linux directory. For the reader interested in kernels, this directory is a very good reference.
The first place to start is to see what header files you have available in the
include directory. This way, you can tell what system services are available.
(See Table 56.1.) I have deliberately left out redundant or unused header files.
By examining the header files, you can see what files and hardward configurations
are available for you in Linux.
Table 56.1. Linux header files in /usr/src/linux/include/linux.
File | Description |
a.out.h | Generated for the GNU C compilers. |
atalk.h | Appletalk network structures and definitions. |
autoconf.h | Automatically generated C config file. Don't edit it! |
ax25.h | Definitions for the AX.25 protocol. |
aztcd.h | Definitions for a AztechCD268 CD-ROM interface. |
binfmts.h | Binary formats for the files. |
bios32.h | BIOS32, PCI BIOS functions and defines. |
blkdev.h | Block device information. |
busmouse.h | Header file for Logitech Bus Mouse driver. |
cdrom.h | General header for all CD-ROM drives. |
cdu31a.h | Definitions for a Sony interface CD-ROM drive. |
cm206.h | Definitions for a CM206 CD-ROM drive and adapter. |
coff.h | The COFF file format definitions. |
config.h | Linux kernel configuration header. |
ctype.h | Standard C types header. |
cyclades.h | For the Cyclades devices. |
debugreg.h | Debug registers header file. |
delay.h | Delay routines using a precomputed loops_per_second value. |
elf.h | The Executable and Linking Format (ELF) definitions. |
errno.h | The standard error return definitions. |
etherdevice.h | Ethernet device handlers declarations. |
ext2_fs.h | The new extended file system (e2fs) declarations. |
ext_fs.h | The ext file system (efs) definitions for older Linux versions. |
fcntl.h | The standard file control declaration. |
fd.h | Floppy disk software control definitions. |
fdreg.h | Definitions for the floppy disk controller. |
fs.h | Definitions for some important file table structures. |
genhd.h | Generic hard disk header declarations. |
gscd.h | Definitions for a GoldStar R420 CD-ROM interface. |
hdreg.h | Declarations for the AT hard disk controllers. |
head.h | Headers for Intel Global and Interrupt Descriptor tables. |
hpfs_fs.h | OS/2 HPFS file system. |
icmp.h | Definitions for the ICMP protocol. |
if.h | Definitions for the INET interface module. |
if_arp.h | Definitions for the ARP (RFC 826) protocol. |
if_ether.h | Definitions for the Ethernet IEEE 802.3 interface. |
if_fw.h | Definitions for an IP firewall module. |
if_plip.h | PLIP tuning facilities for the new Niibe PLIP. |
if_ppp.h | Constants and structures for use with the PPP module. |
if_slip.h | Constants for special use with the SLIP/CSLIP/KISS TNC driver. |
igmp.h | Internet Gateway Management Protocol (IGMP). |
in.h | Definitions of the Internet Protocol. |
in_systm.h | Miscellaneous Internetwork definitions for the Linux kernel. |
inet.h | Internet Protocol headers. |
interrupt.h | For Linux interrupt drivers. |
ioctl.h | Standard I/O control definitions. |
ioport.h | For detecting, reserving, and allocating system resources. |
ip.h | Definitions for the IP protocol. |
ipc.h | For interprocess communication. |
ipx.h | For sockets in network programming. |
iso_fs.h | The ISO file system headers. |
kd.h | Kernel development declarations. |
kernel.h | Kernel header file declarations. |
kernel_stat.h | More kernel statistics header file declarations. |
keyboard.h | Declaration for using the keyboard. |
ldt.h | Definitions for use with Local Descriptor Tables. |
limits.h | Limits for the kernel to use. |
linkage.h | Linking declarations for the kernel. |
locks.h | File locking definitions. |
lp.h | Line printer support header. |
major.h | Major device number header. |
malloc.h | Standard memory management function header. |
math_emu.h | Math emulation declarations. |
mc146818rtc.h | Register definitions for RealTime Clock and CMOS RAM. |
mcd.h | Definitions for a Mitsumi CD-ROM interface. |
mcdx.h | Definitions for the Mitsumi CD-ROM interface. |
minix.h | The minix file system constants/structures. |
mm.h | Memory manager for kernel. |
mman.h | Memory mapping definitions. |
module.h | For use with dynamic loading of modules into the kernel. |
mouse.h | For use with serial mouse. |
msdos_fs.h | The MS-DOS file system constants/structures. |
msg.h | For message processing in Linux IPC. |
mtio.h | Definitions for magnetic tape I/O functions. |
net.h | Implementation file for the networking portion of the Linux kernel. |
optcd.h | Definitions for the Optics Storage 8000AT CD-ROM drive. |
param.h | Internal Linux parameters header. |
pci.h | PCI bus defines and function prototypes. |
personality.h | Linux file personality declarations. |
pipe_fs_i.h | For use with Linux file pipes. |
ppp.h | For use with Point-to-Point Protocol with Linux. |
proc_fs.h | The proc file system constants/structures. |
ptrace.h | Defines to help the user use the ptrace system call. |
resource.h | Resource control/accounting header file for Linux. |
route.h | Global definitions for the IP router interface. |
sbpcd.h | For Panasonic CD-ROM drives. |
sched.h | The Linux task scheduler. |
scsicam.h | SCSI CAM support functions, use for HDIO_GETGEO, and so on. |
sem.h | For use with semaphores on Linux. |
serial.h | Linux serial I/O definitions. |
serial_reg.h | For the UART port assignments. |
shm.h | For shared memory use on Linux. |
signal.h | For Linux signal information. |
sjcd.h | Definitions for a Sanyo CD-ROM drive. |
skbuff.h | Definitions for the struct sk_buff memory handlers. |
socket.h | More declarations of the socket-level I/O control calls. |
sockios.h | More declarations of the socket-level I/O control calls. |
sonycd535.h | Defines all of the commands for the CD-ROMs by Sony (CDU-531-5). |
soundcard.h | For interfacing with soundcards. |
stat.h | Standard C and UNIX definitions. |
stddef.h | Standard C definitions. |
string.h | String functions declarations for C programmers. |
symtab_begin.h | Symbol table entries. |
symtab_end.h | Symbol table entries. |
sys.h | System call entry points. |
sysv_fs.h | The SystemV/Coherent file system definitions. |
tasks.h | For specifying the maximum number of tasks at one time in Linux. |
tcp.h | Definitions for the TCP protocol. |
termios.h | Terminal I/O declarations. |
time.h | Standard declarations for use with timers. |
timer.h | Do not modify this timer declarations file. |
times.h | For use with Linux kernel timers. |
timex.h | For TIMEX devices. |
tpqic02.h | include file for the QIC-02 driver for Linux. |
tqueue.h | The task queue handling information for Linux. |
tty.h | Defines some structures used by tty_io.c. |
tty_driver.h | Defines interface between low-level tty driver and its routines. |
types.h | Standard Linux variable type definitions. |
udp.h | Definitions for the UDP protocol. |
ultrasound.h | For Ultrasound CD-ROM devices. |
umsdos_fs.h | The UMSDOS file system header. |
un.h | Linux header for socket programming. |
unistd.h | Standard UNIX file header. |
user.h | For use with core dumps and user segments. |
utime.h | Time information. |
utsname.h | Time information and structures. |
version.h | Linux version information. |
vfs.h | Virtual file system headers. |
vm86.h | Virtual memory management routines. |
vt.h | For use with virtual terminals. |
xd.h | Definitions for the I/O ports, and so forth, for XT hard disk contollers. |
modules/ | Contains the file ksyms.ver, a symbol version table generated by genksyms. |
Let's give an example of how you would use this header file information. Suppose that using the default kernel for the sbcpd (Panasonic CD-ROM) drive takes a long time to boot because it probes the I/O ports to see where the drive is in the I/O port memory space. You know you have set your jumpers on the drive to 0x260, so why not just have it look there and keep going? You are sick of typing in the sbpcd=0x260,SoundBlaster sequence every time you boot.
Sounds good. Let's look at the sbpcd.h file in /usr/src/linux/include/linux.
First, log in as root and make sure that you have write privileges to this header file to save your changes. Look at the part of the file where it says to define your CD-ROM port base I/O address as CDROM_PORT and specify the type of your interface card as SBPRO. You can change the address lines in file after line 90 as the following:
#undef CDROM_PORT /* get rid of previous declarations. */ #undef SBPRO /* get rid of previous declarations. */ #undef SOUND_BASE /* get rid of previous declarations. */ /* override these values. */ #define CDROM_PORT 0x230 /* port address */ #define SBPRO 0 /* interface type */ #define SOUND_BASE 0x220 /* sound address of this card or 0 */
Now exit the editor after making the changes. Rebuild the kernel and install it as discussed earlier in this chapter. Reboot, and there you have it--a fast boot.
This is only a quick example of how to use this valuable resource of information to customize your Linux system. I am sure that with some exploring, you can come across some more examples.
We briefly covered modules in Chapter 5, "Special Installations." This section describes the basic strategy for making dynamically loadable modules in the Linux kernel. Let's look at how to use them. However, how modules work is really beyond the scope of this book. Sorry.
In this kernel version (2.0.0 or later versions), you can also create modules by enabling CONFIG_MODVERSIONS when making a kernel. Also, you have to install the latest module support package modules-2.0.0.tar.gz (or later version.) Next, compile and install the kernel (as explained earlier).
When you have made the kernel, create the modules by typing the following command:
make modules
This compiles all modules and updates the modules directory. In this directory, you can then find a bunch of symbolic links, pointing to the various object files in the kernel tree.
The set of modules is rapidly increasing, and you have the following list of items with this CD-ROM. You can find descriptions for each of these modules by following each of the links in the files in the directory usr/src/linux/modules:
As soon as you have rebooted the newly made kernel, you can install and remove modules at will with the utilities insmod and rmmod.
Now, after you have made all modules, you can also type the following command:
make modules_install
This copies all newly made modules into subdirectories under /lib/modules/kernel_release/where kernel_release is something like 1.2.13, or later.
Using the modprobe utility, you can load any module like this:
/sbin/modprobe module
To use modprobe successfully, you should place the following command in your /etc/rc.d/rc.S script:
/sbin/depmod -a
This computes the dependencies between the different modules. Then type the following line, for example:
/sbin/modprobe umsdos
Now you automatically load both the MS-DOS and UMSDOS modules, because UMSDOS runs piggyback on MS-DOS.
Another important file to look at is the rc.modules file. This file is located in the /etc/rc.d directory and is executed when the system first boots up. The latest version of this rc.modules file is version 1.11 by Sam Volkerding for Slackware Linux. More documentation for specific modules is listed in the /docs directory on the CD-ROM.
Edit the rc.modules file carefully and keep a backup copy of this file before you make too many edits. Each line in the rc.modules corresponds to a binary file to execute to load a module into Linux. Most of the entries in the rc.modules file will be commented out. Uncomment only the lines you need. It'll probably be easier if you uncomment one line at a time instead of uncommenting all the lines at once. Some modules might require other modules to be loaded before being loaded themselves, or might not allow the code to be loaded more than once. These exceptions are special cases indeed. For example, you have to load the MS-DOS module before you load USMSDOS. For example, you cannot load the NE2000 module twice if you have more than one Ethernet card in your system. In some cases, you will simply have to rebuild a kernel and statically link in the features you need.
Be prepared to boot several times to get the exact sequence of loaded modules for your custom setup. In general, the modules in rc.modules are listed in the order they should be in to satisfy any interdependencies between modules.
Recompiling kernel source and adding new features to the kernel proceeds smoothly, as long as you know what you are doing. Don't let the process scare you, but always keep boot disks on hand. Follow instructions wherever available, because most new software has special requirements for linking into the kernel or replacing existing systems.