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.
