Compiling and Loading

The rest of this chapter is devoted to writing a complete, though typeless, module. That is, the module will not belong to any of the classes listed in Section 1.3, in Chapter 1. The sample driver shown in this chapter is called skull, short for “Simple Kernel Utility for Loading Localities.” You can reuse the skull source to load your own local code to the kernel, after removing the sample functionality it offers.[4]

Before we deal with the roles of init_module and cleanup_module, however, we’ll write a Makefile that builds object code that the kernel can load.

First, we need to define the __KERNEL__ symbol in the preprocessor before we include any headers. This symbol is used to select which parts of the headers are actually used. Applications end up including kernel headers because libc includes them,[5] but the applications don’t need all the kernel prototypes. Therefore, __KERNEL__ is used to mask the extra ones out via #ifdef. Exporting kernel symbols and macros to user-space programs would greatly contribute to program namespace pollution. If you are compiling for an SMP (Symmetric Multi-Processor) machine, you also need to define __SMP__ before including the kernel headers. This requirement may seem unfriendly, but is going to disappear as soon as the developers find the right way to be SMP-transparent.

Another important symbol is MODULE, which must be defined before including <linux/module.h>. This symbol is always defined, except when compiling ...

Get Linux Device Drivers now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.