Библиотека сайта rus-linux.net
Linux System Administrator's Survival Guide lsg25.htm
Chapter 25
Modifying the Kernel
Usually you will want to leave the Linux kernel alone except when performing a major upgrade, installing a new networking component (such as NFS or NIS), or installing a new device driver that has special kernel requirements. The details of the process used to install the kernel drivers are usually supplied with the software. Because this isn't always the case, though, this chapter should give you a good idea of the general process for working with the kernel.
<NOTE>Don't modify the kernel without knowing what you are doing. If you damage the source code or configuration information, your kernel may be unusable, and in the worst cases, your filesystem may be affected. Take care and follow instructions carefully. keep in mind that this chapter only covers the basics of kernel manipulation.<NOTE>
The several versions of Linux in common use have a few inconsistencies between them. For that reason, the exact instructions supplied in the following sections may not work with your version of Linux. The general approach is the same, however, 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.
<NOTE>Before doing anything with the kernel or utilities, make sure you have a good set of emergency boot disks and a complete backup on tape or floppy disk. Although the process of modifying the kernel is not difficult, it does cause problems every now and again that can leave you stranded without a working system. Boot disks are the best way to recover, so make at least one extra set.<NOTE>
Because the kernel is compiled with the C compiler supplied as part of Linux, the latter part of this chapter looks at the C compiler and its flags and how you can use it to your advantage. This information isn't meant to be a complete reference to the C system, of course, but it should be useful for some basic manipulations you may require when modifying the kernel (or any other source code compiled by C).
Upgrading and Installing New Kernel Software
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 you want to upgrade to the new releases usually depends on the features or bug fixes that the new release offers. You will probably have to relink the kernel when you add new software, unless the software is loaded as a utility or device driver.
Avoid upgrading your system with every new release, for a couple of reasons. The most common problem with constant upgrades is that you may be stuck with a new software package that causes backward compatibility problems with your existing system or that has a major problem with it. Most new releases of software wipe out existing configuration information, so you will have to reconfigure the packages that are being installed from scratch. Also, the frequency with which new releases are made available is so high that you can probably spend more time loading and recompiling kernels and utilities than using the system. Read the release notes carefully to ensure that the release is worth the installation time and trouble. Remember that few installations proceed smoothly!
The best advice is to upgrade only once or twice a year, and only when there is a new feature or enhancement that will make a significant difference to the way you use Linux. It's tempting to always have the latest and newest versions 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 five 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 method saves time and reconfiguration.
Compiling the Kernel from Source Code
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 filesystem 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 with no need to do anything more than start the upgrade utility.
Where to Find Kernel Sources
Kernel sources for new releases of Linux are available from CD-ROM distributions, FTP sites, user groups, and many other locations. Most kernel versions are numbered with a version and a patch level, so you see kernel names like 1.12.123 where 1 is the major release, 12 is the minor version release, and 123 is the patch number. Most kernel source sites 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. In most cases, the patch overlays a section of existing source code, and you only need to recompile the kernel 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 of /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.
Using New Kernel Sources
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) file so you have a backup version in case of problems.
After unpacking the kernel source, 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 the following:
ln -sf /usr/src/linux/include/linux /usr/include/linux
ln -sf /usr/src/linux/include/asm /usr/include/asm
If the directory names are different with your version of Linux, substitute them for /usr/src/linux. Without these links, the upgrade or installation of a new kernel cannot proceed.
After ungzipping and untarring the source code and establishing the links, you can begin the compilation process. 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; 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 Makefile is in with your source distribution). This file has a line that defines the ROOT_DEV, the device that is used as the root filesystem when Linux boots. Usually the line looks like the following:
ROOT_DEV = CURRENT
If you have any other value, make sure it is correct for your filesystem configuration. If the Makefile has no value, set it as shown in the preceding line.
The compilation process begins with you changing to the /usr/src/linux directory and issuing the command
make config
which invokes the make utility for the C compiler. The process may be slightly different for some versions of Linux, so check any release or installation notes supplied with the source code.
The config program issues a series of questions and prompts you to answer to indicate any configuration issues that need to be completed before the compilation begins. These questions may be about the type of disk drive you are using, the CPU, any partitions, or other devices like CD-ROMs. Answer the questions as well as you can. If you are unsure, choose the default values or the one that makes the most sense. The worst case is that you will 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 step is commonly skipped and can cause a lot of problems if 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 the release or installation notes to ensure that the dependencies are correctly handled by the other steps.
Now you can finally compile the new kernel. The command to start the process is
make Image
which 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 following 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 disk. To place the kernel on a floppy disk, use the following command:
cp Image /dev/fd0
Use a different device driver as necessary to place the kernel elsewhere on the hard drive filesystem. 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. Don't copy the new kernel over your old boot disk's kernel. If the new kernel doesn't boot, you may have to use the older boot disk to restart your system.
Now all that remains is to reboot the system and see whether the new kernel loads properly. If you have any problems, boot from a floppy disk, restore the old kernel, and start the process again. Check 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.
Adding Drivers to the Kernel
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 procedure is often necessary when you add a new device like 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.
Add-in kernel software usually has installation instructions provided, but the general process is to locate the source in a directory that the kernel recompilation process can find (such as /usr/src). Instructing the make utility to add the new code to the kernel may require modifications to the Makefile. Either you or an installation script can make these modifications. Some software has its own Makefile supplied for this reason.
Then, begin the kernel recompilation with the new software added in to the load. The process is the same as shown in the preceding section, with the kernel installed in the boot location or set by LILO. Typically, the entire process takes about 10 minutes and is quite troublefree unless the vendor of the kernel modification did a sloppy job. Make sure that the source code provided for the modification works with your version of the Linux kernel.
Upgrading Libraries
Most of the software on a Linux system is set to use shared libraries (a set of subroutines used by many programs). When the message
Incompatible library version
appears on-screen after you upgrade 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 backwards-compatible, so existing software should work properly even after a library upgrade.
Library upgrades are less frequent than kernel upgrades and can be found 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 the target directories are usually /lib, /usr/lib, and /usr/include. Usually, any files that have the extension .a or .aa go 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 filesystem to point to the latest version of the library. For example, if you were running library version libc.so.4.4.1 and upgraded to libc.so.4.4.2, you must alter the symbolic link set in /lib to this file. The command would be
ln -sf /lib/libc/so/4/4/1 /lib/libc.so.4
where the last name 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 will also have to change the symbolic link for the file libm.so.version in the same manner. Do not delete the symbolic links; if you do, all programs that depend on the shared library (including ls) will be unable to function.
Using Linux's C Compiler
Linux uses a C compiler for every compilation of the kernel (and most utilities, too). The C compiler that is available for all versions of Linux is the GNU C compiler, abbreviated gcc. This compiler was created under the Free Software Foundation's programming license and is therefore freely distributable. The GNU C Compiler that is packaged with the Slackware Linux distribution is a fully functional ANSI C compatible compiler. If you are familiar with a C compiler on a different operating system or hardware platform, you will be able to learn gcc very quickly.
The GCC compiler is invoked by passing it a number of options and one or more filenames. The basic syntax for gcc is as follows:
gcc [options] [filenames]
The operations specified by the command line options are performed on each of the files that are on the command line. There are well over 100 compiler options that can be passed to gcc. You will probably never use most of these options, but you will use some of them on a regular basis.
Compiler Options
Many of the gcc options consist of more than one character. For this reason, you must specify each option with its own hyphen. You cannot group options after a single hyphen as you can with most Linux commands. For example, the following two commands are not the same:
gcc -p -g test.c
gcc -pg test.c
The first command tells gcc to compile test.c with profile information (-p) and also to store debugging information with the executable (-g). The second command just tells gcc to compile test.c with profile information for the gprof command (-pg).
When you compile a program using gcc without any command line options, it creates an executable file (assuming that the compile was successful) and calls it a.out. To specify a name other than a.out for the executable file, you use the -o compiler option. For example, to compile a C program file named count.c into an executable file named count, use the following command:
gcc -o count count.c
As shown in the preceding example, the executable file name must occur directly after the -o on the command line.
Other compiler options enable you to specify how far you want the compile to proceed. The -c option tells gcc to compile the code into object code and to skip the assembly and linking stages of the compile. This option is used quite often because it makes the compilation of multifile C programs faster and easier to manage. Object code files that are created by gcc have a .o extension by default.
The -S compiler option tells gcc to stop the compile after it has generated the assembler files for the C code. Assembler files that are generated by gcc have a .s extension by default. The -E option instructs the compiler to only perform the preprocessing compiler stage on the input files. When this option is used, the output from the preprocessor is sent to the standard output rather than being stored in a file.
When you compile C code with gcc, it tries to compile the code in the least amount of time and also tries to create compiled code that is easy to debug. Making the code easy to debug means that the sequence of the compiled code is the same as the sequence of the source code and no code gets optimized out of the compile. There are many options that you can use to tell gcc to create smaller, faster executable programs at the cost of compile time and ease of debugging. Of these options, the two that you will use most are the -O and the -O2 options.
The -O option tells gcc to perform basic optimizations on the source code. These optimizations make the code run faster in most cases. The -O2 option tells gcc to make the code as fast and small as it can. The -O2 option causes the compilation speed to be slower than it is when using the -O option, but it typically results in code that executes more quickly.
In addition to the -O and -O2 optimization options, you can use a number of lower-level options to make the code faster. These options are very specific and should only be used if you fully understand the effect of these options on the compiled code. For a detailed description of these options, refer to the gcc man page.
Debugging and Profiling Options
The gcc compiler supports several debugging and profiling options. Of these options, the two that you are most likely to use are the -g option and the -pg option.
The -g option tells GCC to produce debugging information that the GNU debugger (gdb) can use to help you to debug your program. The gcc program provides a feature that many other C compilers do not have. With gcc, you can use the -g option in conjunction with the -O option (which generates optimized code). This feature can be very useful if you are trying to debug code that is as close as possible to what will exist in the final product. When you are using these two options together, be aware that gcc will probably change some of the code that you have written when gcc optimizes the code.
The -pg option tells gcc to add extra code to your program that, when executed, generates profile information that the gprof program uses to display timing information about your program.
Debugging gcc Programs with gdb
Linux includes the GNU debugging program called gdb. You can use gdb debugger to debug C and C++ programs. It enables you to see the internal structure or the memory that a program is using while it is executing. This debugging program enables you to perform the following functions:
- Monitor the value of variables that your program contains
- Set breakpoints that stop the program at a specific line of code
- Step through the code line by line
When you start gdb, you can specify a number of options on the command line. You will probably run gdb most often with this command:
gdb filename
When you invoke gdb in this way, you are specifying the executable file that you want to debug. You can also tell gdb to inspect a core file that was created by the executable file being examined or attach gdb to a currently running process. To get a listing and brief description of each of these other options, refer to the gdb man page or type gdb -h at the command line.
To get gdb to work properly, you must compile your programs so that the compiler generates debugging information. The debugging information that is generated contains the types for each of the variables in your program as well as the mapping between the addresses in the executable program and the line numbers in the source code. The gdb debugging program uses this information to relate the executable code to the source code. To compile a program with the debugging information turned on, use the -g compiler option.
Summary
Recompiling the 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 as most new software has special requirements for linking into the kernel or replacing existing systems.