Chapter 2 : Building Linux Kernel
In the previous chapter we had an introduction of linux kernel. Now, let’s take another task - configuring , building , installing and packaging linux kernel. One point , very important , for entire kernel build procedure, all the commands must be issued at the root of kernel sources . Assuming the kernel sources are kept under /usr/src/linux-2.6.33.1 ,
# cd /usr/src/linux-2.6.33.1
All the commands for configuring and building kernel will be issued from here. If you are at the root of kernel sources, then you must be seeing Makefile here. This is kernel’s root Makefile. Open this Makefile , on top of this Makefile , you will find variables with name VERSION, PATCHLEVEL , SUBLEVEL and EXTRAVERSION . Version number string of the kernel image, that we build with these sources will be formed with the values given in these variables. We are going to build our own new kernel image with these sources. This new image should also have a version for identification. Just modify the value given in EXTRAVERSION to .1MyLinux . Effect of this change is that the version of the kernel image that we will build with these sources will be 2.6.33.1MyLinux. When you boot the system after building and installing your new kernel image ,this version string will appear as a boot option. You can select this new version and your new kernel image will boot.
2.1 Configuration :
The greatest advantage of having linux kernel source code open is the capability that you can customize/configure the kernel as per your need. As we discussed under integration design in the previous chapter, main kernel image is built as a static image, and some part of linux kernel image is also built as loadable modules. Kernel’s static image is always resident in memory while some services are added to the kernel at runtime in the form of modules. Complete kernel image constitute static kernel image plus run-time loadable modules. Linux kernel configuration allows you to decide , which feature you want to include in linux kernel image , which feature you do not want to include or which service you want to make as a loadable kernel module etc. There are many tools available in linux for configuring the kernel , we will try to cover all important ones.
2.1.1. Text Based Configuration :
2.1.1.1 Interactive Configuration:
‘make config’ is an interactive text based kernel configuration utility. Infact it is useful for quite experienced kernel developers and not for the beginners. The result of this command is shown below.
# make config scripts/kconfig/conf arch/x86/Kconfig * * Linux Kernel Configuration * * * General setup * Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [N/y/?] y Local version - append to kernel release (LOCALVERSION) [] y Automatically append version information to the version string (LOCALVERSION_AUTO) [N/y/?] y Kernel compression mode > 1. Gzip (KERNEL_GZIP) 2. Bzip2 (KERNEL_BZIP2) 3. LZMA (KERNEL_LZMA) 4. LZO (KERNEL_LZO) choice[1-4?]: 1 Support for paging of anonymous memory (swap) (SWAP) [N/y/?] y System V IPC (SYSVIPC) [N/y/?] y BSD Process Accounting (BSD_PROCESS_ACCT) [N/y/?] y BSD Process Accounting version 3 file format (BSD_PROCESS_ACCT_V3) [N/y/?] (NEW) y * * RCU Subsystem * RCU Implementation > 1. Tree-based hierarchical RCU (TREE_RCU) 2. UP-only small-memory-footprint RCU (TINY_RCU) choice[1-2]: 1 Enable tracing for RCU (RCU_TRACE) [N/y/?] y Tree-based hierarchical RCU fanout value (RCU_FANOUT) [32]
Fig. 2.1 ‘make config’ utility
This command starts an interactive kernel configuration script which continuously prompts for user input at every step . User can enter any one of the four options,
1) Yes – For building the particular feature with kernel’s static image.
2) No – For not including the feature at all in the kernel image.
3) Module – For building this feature as loadable kernel module.
4) ? – For help , gives brief description of the feature.
Like you saw above in the command output, the script steps through all the configuration options available and asks for user input . Script prompts for each and every option and expects the input for each of the options. There are so many options available so it is very tedious and time consuming way. Now you can guess the reason why it not a
preferred way to configure linux kernel.2.1.1.2 Default Configuration:
# make defconfig
*** Default configuration is based on 'i386_defconfig'
#
# configuration written to .config
#
# make defconfig
*** Default configuration is based on 'i386_defconfig'
#
# configuration written to .config
#
This utility generates default configuration for linux kernel. This default configuration is based on the configuration options preferred and used by linux kernel maintainers on their own machines. Once you create the default configuration , you can view and modify it as per your need later.
There are few other kernel configuration targets like oldconfig , randconfig, allmodconfig, allyesconfig, allnoconfig. These options are left to you to explore as an exerciseJ .
2.1.2 Console based configuration :
Here comes a very popular way of configuring kernel ,
# make menuconfig
Fig. 2.3 ‘make menuconfig’ utility
As you are seeing in the figure, this command opens a graphical console in which all kernel configuration options are arranged nicely into different categories. These categories arefurther subdivided into subcategories. You just have to browse through and keep on selecting options until you reach the specific configuration option. It is much more easier than it looks in the first instance. You just have to watch the screen and browse options carefully. If you are going to build the kernel for the first time , then 'Exit' without doing any modification. A configuration file, .config will be created for you for further use.
2.1.3 GUI Based Configuration :
2.1.3.1 X11 Based Configuration:
# make xconfig
# make xconfig
Fig. 2.4 ‘make xconfig’ utility
Make xconfig is X11-based graphical configuration utility. It arranges all the configuration options into left and right pane nicely. You can easily browse through and select different options easily.
2.1.3.2 GTK Based Configuration:
# make gconfig
# make gconfig
Fig.2.4 ‘make gconfig’ utility
gconfig is gtk+ based graphical configuration utility. Xconfig and gconfig are almost similar in nature but personally I feel gconfig looks cleaner and is easier to use. You can play with these above three utilities and can opt whichever you felt better with. Since this is the very first time we are going to build the kernel , we will not experiment with the default kernel configuration and would take the default configuration as it is . You can run 'make defconfig' to generate default configuration for linux kernel. Alternatively you can also use 'make menuconfig' or 'make xconfig' or 'make gconfig' to generate default kernel configuration. Just run any of those commands , do not make any chaneges and save and exit from them graphical editor . Once you have completed kernel configuration by any of the above ways discussed above , a file with name .config will be created under the root of kernel source tree. This .config file was not present when you took kernel sources from kernel.org. It will be created when you complete kernel configuration for the first time. It is a text file and it contains all the configuration options and their details. By seeing this .config file you can get to know if a particular feature is included/excluded in kernel image or if it is built as a module . At kernel build time , the input is taken from this file only. After some experience you can directly edit this file to tell kernel build system about which feature you want to include/exclude in kernel image .
# vi .config # Automatically generated make config: don't edit # Linux kernel version: 2.6.33MyLinux # Wed Apr 14 02:49:26 2010 # # CONFIG_64BIT is not set CONFIG_X86_32=y # CONFIG_X86_64 is not set CONFIG_X86=y CONFIG_OUTPUT_FORMAT="elf32-i386" CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_CLOCKSOURCE_WATCHDOG=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y CONFIG_MMU=y
Fig.2.5 .config file
You can see above that all configuration options are listed and ‘yes’ , ‘no’ and ‘module’ against them . 'yes' is for including this feature in kernel image, 'no' is for not including this feature in kernel image and 'module' is for building this feature as a runtime loadable module. You can see that if you have fair idea about different configuration options , you you can modify the file and generate your own configuration easily.
2.2 Building :
Once we have decided about what features we want to include in the kernel image that we are going to build , we can rightaway starts building. Again , you should be at the root of the kernel sources.
Now just issue command ,
# make CHK include/linux/version.h CHK include/generated/utsrelease.h CALL scripts/checksyscalls.sh CHK include/generated/compile.h CC arch/x86/kernel/signal.o AS arch/x86/kernel/entry_32.o CC arch/x86/kernel/traps.o CC arch/x86/kernel/irq.o CC arch/x86/kernel/irq_32.o CC arch/x86/kernel/dumpstack_32.o CC arch/x86/kernel/time.o CC arch/x86/kernel/ioport.o CC arch/x86/kernel/ldt.o CC arch/x86/kernel/dumpstack.o CC arch/x86/kernel/setup.o CC arch/x86/kernel/x86_init.o CC arch/x86/kernel/i8259.o CC arch/x86/kernel/irqinit.o CC arch/x86/kernel/probe_roms_32.o CC arch/x86/kernel/sys_i386_32.o CC arch/x86/kernel/i386_ksyms_32.o CC arch/x86/kernel/bootflag.o CC arch/x86/kernel/e820.o CC arch/x86/kernel/pci-dma.o
Fig. 2.5 Output of make
Linux kernel has one Makefile under the root of kernel source tree. This Makefile is called root Makefile . Make command uses this root Makefile to build the kernel. Also, There are subMakefiles present in each subdirectory of kernel source tree. These submakefiles are used to compile a particular subdirectory or a single file in that subdirectory . The root Makefile uses these submakefiles . All the subdirectories/features are compiled into .o files first , later linker links them and creates a file named Vmlinux. After the completion of make command , you can see a file with a name vmllinux under the root of kernel sources. This vmlinux is compiled kernel image of all the services that we have chosen.
1. The virtual addresses specified in the vmLinux are translated to architecture specific physical addresses. At this point , dont worry about virtual and physical addresses, we have lot more to say about them in susequent chapters.
2. An startup code called bootstrap is added to this image.
After above two steps compressed, loadable and bootable kernel image , 'bzImage' is generated. You will see the
bzImage under arch directory. Here completes your kernel build !!In case, later on if you want to modify some of the code file , you don’t need to rebuild the entire kernel from the scratch. Instead you can build only the changed source file and link that with the kernel image . For example, if you have made changes to file named mm\page_alloc.c, then rebuild just that particular file by using command ,
#make mrproper: cleans up all the config files of previous build .
After cleaning up old build files , you can issue 'make' command to re-build the kernel. That’s enough for kernel build procedure !!
2.3 Installation:
Installation of the kernel image is a two step process. First step deals with the installation of the kernel modules and static vmlinuz. This is achieved by copying the static vmlinuz and all loadable kernel modules to their appropriate locations.
The second step deals with the modification of the bootloader configuration file.
2.3.1 Installing Image and Modules:
The ‘make’ command builds all the loadable kernel modules in some temporary directory. We need to copy all those modules to the correct location. In our case the correct location is /lib/modules/2.6.14.MyLinux/.
Thankfully this process is automated and it can simply be achieved by using command ,
# make modules_install |
Next, we need to install the static kernel image i.e. vmlinuz. vmlinuz should be placed to a location where bootloader program can locate and boot it.
This process too is automated and is achieved by giving command ,
# make install |
For intel based PC, this command copies the vmlinuz from /arch/i386/boot/vmlinuz to /boot directory.
2.3.2 Modifying Bootloader configuration:
The bootloader program searches for the kernel image in the /boot directory. This is the reason why bzimage is copied from /arch/i386/boot/vmlinuz to the /boot directory.
If bootloader finds the particular bzImage under /boot directory, it loads the image into memory and booting starts. Bootloader should know the name of the kernel image for
searching it under /boot directory. Bootloader reads the name of kernel image from its configuration file. So,we need to edit the bootloader configuration file to tell the name of
our kernel image to the bootloader.
There are two bootloaders used for booting the linux kernel , grub and lilo. Eventually grub (Grand Unified Bootloader) has become the default bootloader for linux.
There are very rare chances of using the lilo. For configuring grub , just open its configuration file , /boot/grub/grub.conf. In case you cant find this file , then you are using lilo and not the grub .
Let’s see the grub configuration file, /boot/grub/grub.conf.
# vi /boot/grub/grub.conf # grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You do not have a /boot partition. This means that # all kernel and initrd paths are relative to /, eg. # root (hd0,6) # kernel /boot/vmlinuz-version ro root=/dev/sda7 # initrd /boot/initrd-version.img #boot=/dev/sda default=0 timeout=5 splashimage=(hd0,6)/boot/grub/splash.xpm.gz hiddenmenu title Fedora (2.6.25-14.fc9.i686) root (hd0,6) kernel /boot/vmlinuz-2.6.25-14.fc9.i686 ro root=UUID=db522622-a376-4d94-bf8c-7b4890d187df rhgb quiet initrd /boot/initrd-2.6.25-14.fc9.i686.img title Other rootnoverify (hd0,0) chainloader +1 |
Fig.2.6 original /boot/grub/grub.conf
In configuration file ,the section starting with ‘title’ corresponds to a kernel image entry. Just copy this section at the end and edit it to include our new kernel image.
The modified file will look like below figure ,
# vi /boot/grub/grub.conf # grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You do not have a /boot partition. This means that # all kernel and initrd paths are relative to /, eg. # root (hd0,6) # kernel /boot/vmlinuz-version ro root=/dev/sda7 # initrd /boot/initrd-version.img #boot=/dev/sda default=0 timeout=5 splashimage=(hd0,6)/boot/grub/splash.xpm.gz hiddenmenu title Fedora (2.6.25-14.fc9.i686) root (hd0,6) kernel /boot/vmlinuz-2.6.25-14.fc9.i686 ro root=UUID=db522622-a376-4d94-bf8c-7b4890d187df rhgb quiet initrd /boot/initrd-2.6.25-14.fc9.i686.img title 2.6.33.1MyLinux root (hd0,6) kernel /bzImage-2.6.33.1MyLinux ro root=UUID=db522622-a376-4d94-bf8c-7b4890d187df rhgb quiet initrd /boot/initrd-2.6.25-14.fc9.i686.img title Other rootnoverify (hd0,0) chainloader +1 |
Fig.2.7 modified /boot/grub/grub.conf
After modifying, save and quit from the file. You grub bootloader configuration for our new kernel image is complete. In case ,if you are using lilo bootloader , then open /etc/lilo.conf file . Edit this configuration file . Save, quit and run /sbin/lilo program .
This is how you configure lilo bootloader. Now Reboot the machine. You can see the new kernel image displaying at the boot option. In the boot menu , the name of new kernel image will be same as you mentioned in the titlt.
For example in my case the name of bootable kernel image would be '2.6.33.1MyLinux' . Select it and press enter to boot this new kernel image.
If you have followed everything till now, then the the new kernel image should boot properly. In case , the new kernel image isn’t booting properly , then you have encountered a kernel panic.
But please , you don’t get panic on kernel panic. Your old kernel image hasn’t gone anywhere , you can anytime select your old image and can get your old system workingJ .
At this point, let’s have a review of what all we did till now.
Fig.2.8 Linux kernel build and installation process
2.4 Packaging :
If you wish to install kernel image on a different machine, then you need to create a package of the kernel image. Just take that package to the target machine and install it there.
For creating the build package, while building kernel, give ‘make rpm-pkg’ command instead of giving ‘make’ alone. This command creates bzImage and modules and then pack them into an rpm file.
You can install these rpms on any other machine.
Infact you can create many other packages also , e.g. binary rpm, debian,tar,gzip,bzip2. The packaging command list is below,
# make rpm-pkg : build the kernel as rpm package. # make binrpm-pkg : build the kernel as compiled binary # make deb-pkg : build the kernel for debian only # make tar-pkg : build the kernel as uncompressed tarball # make rargz-pkg : build the kernel as gzip compressed tarball # make tarbz2-pkg : build the kernel as bzip2 compressed tarball
2.5 Illustration :
I have tried building and installing linux kernel on my PC. Fortunatly for me it was very straigtforward and simple. I can summarize the entire process in following steps.
1 - I got the latest 32-bit Fedora Core 13 DVD Image on my intel based PC . You can get the image from http://fedoraproject.org/en/get-fedora-options#formats .
2 - I installed the same image on my PC , I selected all possible packages.
3- Next , I got the latest stable kernel sources , 2.6.34.1 from kernel.org.
4- I unzipped those sources under my home directory , /home/llk/linux-2.6.34.1
5- Under the directory /home/llk/linux-2.6.34.1 , I found one Makefile. Inside this Makefile I modified the EXTRAVERSION string to .LLK.
6 - Now I ran 'make menuconfig' command. I didnt change anything as i wanted to keep the default configuration. I just pressed ' Exit ' , saved the seetings and came out.
7- Now I ran 'make' command. It took long time to complete the make command. You can see various modules building on screen. it may take around 1 hour ,if you have selected everything to build.
8- Once make is complete, I issues 'make modules_install' and 'make install' commands. You have to be root for running these commands. Normal users do not have access to different installation directories.
9- I opened /boot directory. I got vmlinuz present there. This means my installation in complete.
10 - I opened /boot/grub/grub.conf file. You have to be root to view this file. I found entry for my kernel version 2.6.34.LLK is already present there. I dont have any need to edit this file manually. I guess this a recent addition and a great facility.
11- I just rebooted my PC , selected Fedora (2.6.34.LLK) from boot time option , and it booted properly. So easy !!!
Here we have completed our fundamental job of building the linux kernel . From now onwards we will use this kernel in subsequent kernel module development.