Kernel development
Brief items
Kernel release status
The current development kernel is 2.5.59; no development kernels have been released since January 16.Linus is back from his travels, and has merged some 300 patches (as of this writing) into his BitKeeper tree. They include some JFS updates, a number of kbuild changes (including the merge of the new modversions code), a new aic7xxx driver, an ALSA update, various network driver fixes, a number of USB updates, a big rework of the SCSI command block allocation code, and more.
The current stable kernel is 2.4.20; there have been no 2.4.21 prepatches from Marcelo in the last week.
Alan Cox has released a couple of patches, the most recent being 2.4.21-pre4-ac2. Quite a bit of IDE work has been going on, and this patch should be handled carefully. (Indeed, there have been some reports of IDE-related deadlocks with the -ac2 patch).
Kernel development news
Initramfs status
One bit of unfinished 2.5 business is "initramfs," the boot-time root filesystem which is tacked onto the kernel binary image. The plan is to move much of the initialization-time code out of the kernel and into initramfs; the result should be a smaller kernel and a safer, more flexible boot process.The code to support initramfs has been in the kernel for some time. The big missing piece has been on the user space side. Before anything useful can be run in user mode as part of the boot process, there must be a whole environment to build it in. Attaching the C library to the kernel image is not an option that would appeal to many, so a special-purpose C library is needed. That library is "klibc," which has been under development by Greg Kroah-Hartman and others for some time. klibc provides a minimal set of standard functions, written with an eye toward portability and small size.
Greg recently posted an update on klibc. The library seems to be essentially complete, at least until somebody tries to do something requiring functions which have not been provided. The sticking point, at the moment, seems to be a bug in the initramfs unpacking code. Greg is interested in input from anybody who would like to help debug that problem. Once that's been ironed out, it is mostly just a matter of figuring out which boot-time operations should be taken out of the kernel and moved into a user-space implementation. If that is going to happen in 2.5, it would be nice if it happened soon; making major changes to the boot process brings with it a real risk of destabilizing the kernel for a while.
Driver porting: hello world
| This article is part of the LWN Porting Drivers to 2.6 series. |
The obvious place to start in this sort of exercise, of course, is the classic "hello world" program, which, in this context, is implemented as a kernel module. The 2.4 version of this module looked like:
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
int init_module(void)
{
printk(KERN_INFO "Hello, world\n");
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye cruel world\n");
}
One would not expect that something this simple and useless would require much in the way of changes, but, in fact, this module will not quite work in a 2.5 kernel. So what do we have to do to fix it up?
The first change is relatively insignificant; the first line:
#define MODULE
is no longer necessary, since the kernel build system (which you really
should use now, see the next article) defines it for you.
The biggest problem with this module, however, is that you have to explicitly declare your initialization and cleanup functions with module_init and module_exit, which are found in <linux/init.h>. You really should have done that for 2.4 as well, but you could get away without it as long as you used the names init_module and cleanup_module. You can still sort of get away with it (though you may have to ignore some compiler warnings), but the new module code broke this way of doing things once, and could do so again. It's really time to bite the bullet and do things right.
With these changes, "hello world" now looks like:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
This module will now work - the "Hello, world" message shows up in the system log file. What also shows up there, however, is a message reading "hello: module license 'unspecified' taints kernel." "Tainting" of the kernel is (usually) a way of indicating that a proprietary module has been inserted, which is not really the case here. What's missing is a declaration of the license used by the module:
MODULE_LICENSE("Dual BSD/GPL");
MODULE_LICENSE is not exactly new; it was added to the 2.4.10
kernel. Some older code may still lack MODULE_LICENSE calls,
however. They are worth adding; in addition to avoiding the "taints
kernel" message, a license declaration gives your module access to GPL-only
kernel symbols. Assuming, of course, that the module is GPL-licensed.
With these changes, "hello world" works as desired. At least, once you have succeeded in building it properly; that is the subject of the next article.
Driver porting: compiling external modules
| This article is part of the LWN Porting Drivers to 2.6 series. |
KERNELDIR = /usr/src/linux
CFLAGS = -D__KERNEL__ -DMODULE -I$(KERNELDIR)/include -O
all: module.o
Real-world makefiles, of course, tended to be a bit more complicated, but the job of creating a loadable module was handled in a single, simple compilation step. All you really needed was a handy set of kernel headers to compile against.
With the 2.6 kernel, you still need those headers. You also, however, need a configured kernel source tree and a set of makefile rules describing how modules are built. There's a few reasons for this:
- The new module loader needs to have some extra symbols defined at
compilation time. Among other things, it needs to have the
KBUILD_BASENAME and KBUILD_MODNAME symbols defined.
- All loadable modules now need to go through a linking step - even those
which are built from a single source file. The link brings in
init/vermagic.o from the kernel source tree; this object
creates a special section in the loadable module describing the
environment in which it was built. It includes the compiler version
used, whether the kernel was built for SMP, whether kernel preemption
is enabled, the architecture which was compiled for, and, of course,
the kernel version. A difference in any of these parameters can
render a module incompatible with a given running kernel; rather than
fail in mysterious ways, the new module loader opts to detect these
compatibilities and refuse to load the module.
As of this writing (2.5.59), the "vermagic" scheme is fallible in that it assumes a match between the kernel's vermagic.o file and the way the module is being built. That will normally be the case, but people who change compiler versions or perform some sort of compilation trickery could get burned.
- The new symbol versioning scheme ("modversions") requires a separate post-compile processing step and yet another linkable object to hold the symbol checksums.
One could certainly, with some effort, write a new, standalone makefile which would handle the above issues. But that solution, along with being a pain, is also brittle; as soon as the module build process changes again, the makefile will break. Eventually that process will stabilize, but, for a while, further changes are almost guaranteed.
So, now that you are convinced that you want to use the kernel build system for external modules, how is that to be done? The first step is to learn how kernel makefiles work in general; makefiles.txt from a recent kernel's Documentation/kbuild directory is recommended reading. The makefile magic needed for a simple kernel module is minimal, however. In fact, for a single-file module, a single-line makefile will suffice:
obj-m := module.o(where module is replaced with the actual name of the resulting module, of course). The kernel build system, on seeing that declaration, will compile module.o from module.c, link it with vermagic.o, and leave the result in module.ko, which can then be loaded into the kernel.
A multi-file module is almost as easy:
obj-m := module.o module-objs := file1.o file2.oIn this case, file1.c and file2.c will be compiled, then linked into module.ko.
Of course, all this assumes that you can get the kernel build system to read and deal with your makefile. The magic command to make that happen is something like the following:
make -C /path/to/source SUBDIRS=$PWD modules
Where /path/to/source is the path to the source directory for the
(configured and built)
target kernel. This command causes make to head over to the kernel source
to find the top-level makefile; it then moves back to the original
directory to build the module of interest.
Of course, typing that command could get tiresome after a while. A trick posted by Gerd Knorr can make things a little easier, though. By looking for a symbol defined by the kernel build process, a makefile can determine whether it has been read directly, or by way of the kernel build system. So the following will build a module against the source for the currently running kernel:
ifneq ($(KERNELRELEASE),)
obj-m := module.o
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
endif
Now a simple "make" will suffice. The makefile will be read twice; the first time it will simply invoke the kernel build system, while the actual work will get done in the second pass. A makefile written in this way is simple, and it should be robust with regard to kernel build changes.
Morse code kernel panics
Here's one feature which didn't get in before the freeze: morse code kernel panics, recently updated to 2.5 by Tomas Szepe. With this patch, a 2.5 kernel which goes into a panic state will blink out the panic message in morse code using the keyboard LEDs. Possible future enhancements include audio output using the PC speaker or a sound card. One developer has mentioned the possibility of having a nearby machine with a microphone to detect and decode the encoded panic message.One might well be tempted to object that the number of people clamoring for this feature has been relatively small. But there is actually a serious side to this patch. It is well known that production Linux systems never panic, but if, someday, a box were to be struck by a cosmic ray and go down, its owner might like to know about it. Preferably before the "where has your site been this last week?" mail starts to show up. The morse code patch could, with a bit of work, be the beginning of a more general panic notification feature. It could be useful, even if you hope you never actually make use of it.
Patches and updates
Kernel trees
Architecture-specific
Core kernel code
Development tools
Device drivers
Documentation
Filesystems and block I/O
Janitorial
Memory management
Networking
Security-related
Benchmarks and bugs
Miscellaneous
Page editor: Jonathan Corbet
Next page:
Distributions>>
