The Linux Kernel
Module Programming Guide by Ori Pomerantz is a
complete explanation of writing your own LKM. This book is also
available in print.
It is, however, a little out of date and contains an error or two.
Here are a few things about writing an LKM that aren't in there.
The simple hello.c program has a small bug that
causes it to generate a warning about an implicit declaration of
printk(). The warning is innocuous.
The program is also more complicated than it needs to be with current
Linux and depends on your having kernel messaging set up a certain way
on your system to see it work. Finally, the program requires you to
include -D options on your compile command to
work, because it does not define some macros in the source code, where
the definitions belong.
Here is an improved version of hello.c. Compile
this with the simple command
/* hello.c
*
* "Hello, world" - the loadable kernel module version.
*
* Compile this with
*
* gcc -c hello.c -Wall
*/
/* Declare what kind of code we want from the header files */
#define __KERNEL__ /* We're part of the kernel */
#define MODULE /* Not a permanent part, though. */
/* Standard headers for LKMs */
#include <linux/modversions.h>
#include <linux/module.h>
#define _LOOSE_KERNEL_NAMES
/* With some combinations of Linux and gcc, tty.h will not compile if
you don't define _LOOSE_KERNEL_NAMES. It's a bug somewhere.
*/
#include <linux/tty.h> /* console_print() interface */
/* Initialize the LKM */
int init_module()
{
console_print("Hello, world - this is the kernel speaking\n");
/* More normal is printk(), but there's less that can go wrong with
console_print(), so let's start simple.
*/
/* If we return a non zero value, it means that
* init_module failed and the LKM can't be loaded
*/
return 0;
}
/* Cleanup - undo whatever init_module did */
void cleanup_module()
{
console_print("Short is the life of an LKM\n");
} |
In the original design, the LKM increments and decrements its use
count to tell the module manager whether it is OK to unload it. For
example, if it's a filesystem driver, it would increment the use count
when someone mounts a filesystem of the type it drives, and decrement
it at unmount time.
Now, there is a more flexible alternative. Your LKM can register a
function that the module manager will call whenever it wants to know
if it is OK to unload the module. If the function returns a
true value, that means the LKM is busy and cannot
be unloaded. If it returns a false value, the LKM
is idle and can be unloaded. The module manager holds the big kernel
lock from before calling the module-busy function until after its
cleanup subroutine returns or sleeps, and unless you've done something
odd, that should mean that your LKM cannot become busy between the
time that you report "not busy" and the time you clean up.
So how do you register the module-busy function? By putting its
address in the unfortunately named can_unload field
in the module descriptor ("struct module"). The name is truly
unfortunate because the boolean value it returns is the exact opposite
of what "can unload" means: true if the module manager
cannot unload the LKM.
The module manager ensures that it does not attempt to unload the
module before its initialization subroutine has returned or sleeps, so
you are safe in setting the can_unload field
anywhere in the initialization subroutine except after a sleep.