This page is meant to collect up hints on building and changing Linux kernels. It is meant for people with a programming background, who haven't worked with the Linux kernel yet.
Page started by Brenda J. Butler, additions/corrections welcome. Add your credits at the bottom.
The intention is to put some kind of free license on this page that will be DFSG-compliant. So please only add stuff if you will agree to such a license.
Warning: In many places I barely know what I am talking about and I may have gotten command names/file names, mechanisms, etc. wrong. This is meant to document some of the less-well-documented conventions. Hopefully even if it is not 100% correct it will direct you to the solution you are seeking.
Invitation: Of course, this is a wiki. If you see something wrong, don't write me: fix the wiki! --thanks!
(see also the section "Compiling the kernel, Debian Way")
Compiling a 2.6 kernel: Use a 3.x series gcc compiler. 4.x is too new. 2.95 is too old.
Compiling a 2.4 kernel: gcc-2.95, or a 3.x series compiler.
This hint is written 2005/09/27, judge for yourself if it is still applicable when you read it.
Edit the top-level makefile, look for the HOSTCC (2.6 Makefile) or the CC definition (2.4 Makefile), and change the c compiler to be gcc-3.3 (run
ls -la `which gcc`*
to get a list of available gcc compilers).
Altering a kernel variable from a module
If you are debugging, and you want to add a variable to the kernel and alter the value from a module, then you need to add the variable to the kernel (say, in slab.c) and also add a macro invocation EXPORT_SYMBOL(your_variable) in kernel/ksyms.c. It is not sufficient to add EXPORT_SYMBOL(your_variable) in the original kernel file ... unless perhaps if you compile that file with both -DCONFIG_MODULE and -DEXPORT_KSYMS. But kernel/ksyms.c is already compiled with those options, so just put your EXPORT_SYMBOL macro invocation there and be done with it.
For completeness, also put a prototype in the appropriate header file (for me, it was slab.h) so the ksyms.c (and the module) will find it.
Configuring the kernel
You must configure the kernel before you build it. You do this by doing one of the following (they are equivalent):
make xconfig <- only for X environment, not console-only make menuconfig <- ok for console-only make config <- only if you have a ''lot'' of time on your hands
This will create or edit a file called .config in the top level, and will run a generation program to create some .h files (and maybe some makefiles and .c files, and who knows what else?) based on the .config file. When I tried this with fresh 2.6 kernel sources, it looked for an existing config file with the name /boot/config-xxx where it figured out xxx from running uname -r. Since I keep my kernels, System.maps and config files there (as per current conventions) with the version numbers appended, it found the appropriate config-xxx file and used it. NOTE, watch out for this if you're cross-compiling.
Copying a .config file into the top level of your kernel build tree is not sufficient. If you want to avoid the ui experience, run
that will generate the files from the existing .config file.
For 2.6 sources, you can revert to the distributed .config by running
in the toplevel directory. This will overwrite your lovingly crafted .config file with something that came in the tarball. For 2.4 sources, remove the .config in the toplevel directory, and run make oldconfig. This will create a file called .config in the toplevel directory which is something like the file that is shipped in arch/xxx/defconfig. It doesn't hurt to keep copies of your .config file in the directory above the kernel top-level: I call them config-184.108.40.206-bjb.this, and config-2.4.20-that to keep them straight (and avoid overwriting config files from other kernel versions).
For 2.6 sources, there is a new make target called prepare that will bring you from pristine sources + .config file (probably copied from /boot/config-something) to ready-to-compile (this target generates the version.h and utsrelease.h files):
The build and install conventions for the kernel
The kernel can be built into several formats. By default, it gets built into an uncompressed executable called vmlinux. You can ask for a compressed executable (which is built in addition) by specifying the target.
For i386, that target is zImage (gzipped) or bzImage (bzip2'd). Another name might be uImage. Often when installed, this gets copied to /boot/vmlinuz.
After building, vmlinux is found in the top-level directory of the source tree. bzImage, zImage, and uImage are found in the arch/xxx/boot directory. The modules (see next paragraph) are found all over the source tree, whereever their source files are.
Also, the kernel is made of the core part, and the dynamically loadable modules. To build the modules, use the target "modules".
To use the build scripts to install, use the targets "install" and "modules_install".
The modules get installed to a directory hierarchy called /lib/modules/version#. For example, /lib/modules/220.127.116.11. You must build a new set of modules for each kernel version as modules and kernels are tightly coupled (eg, share data structures). The running kernel picks the right set of modules by comparing it's own version number (which you can see from the command
in the shell) to the directories in /lib/modules.
It is easy to install the kernel by hand (just copy the appropriate files to /boot and adjust your bootloader config) but use
to install the modules. It will get them all, and put them in the right place.
irc: irc.oftc.net, #kernelnewbies
In many distros, the boot messages (from the kernel, not from user-space) are collected up in the "kernel ring buffer" until the (user-space) system logging facility is ready to take the messages and write them to disk. If you have debugging turned on in various places in the kernel, the kernel ring buffer might fill up and new messages might over-write the very first messages. You can increase the size of the kernel ring buffer in the config options, see the "kernel hacking" section, "kernel log buffer size" option.
In many distros, these boot-up messages are placed in /var/log/dmesg as soon as user-space and syslogd are able to handle it. At that point, the system will start logging via syslogd and all the messages will end up somewhere in /var/log (or whereever syslog is configured to put them). But the kernel messages still go to the kernel ring buffer in addition.
The user-space program "dmesg(8)" will dump out the (current contents of the) kernel ring buffer, check the man page for more info and for what the options do.
The printk call is the way to send messages to the logs or the ring buffer. Today I learned there is also a pr_debug () call (defined in include/linux/kernel.h). - I saw this in 2.6 kernel, not sure if that would be in 2.4 kernel.
Compiling kernel, Debian Way
There are some tutorials for this...
Don't specify a version in the .config (via menu-config) or directly in the Makefile (EXTRAVERSION) if you are going to use --revision on the make-kpkg command line or you will seriously confuse make-kpkg (and yaird, which is a mkinitramfs replacement).
To specify a custom linux kernel version use --append-to-version. To specify a custom debian package version number use --revision. Don't touch anything else.
* kernel-package 10.023, 10.027, 10.029 * yaird 0.11-12, 0.12-1, 0.12-3 on 2006/01/02 * kernel 18.104.22.168 from kernel.org * (thanks Manoj!)
- Brenda J. Butler