mirror of https://github.com/tLDP/LDP
554 lines
28 KiB
Plaintext
554 lines
28 KiB
Plaintext
<sect1><title>Hello, World (part 1): The Simplest Module</title>
|
|
|
|
<para>When the first caveman programmer chiseled the first program on the walls of the first cave computer, it was a program
|
|
to paint the string `Hello, world' in Antelope pictures. Roman programming textbooks began with the `Salut, Mundi' program.
|
|
I don't know what happens to people who break with this tradition, but I think it's safer not to find out. We'll start with a
|
|
series of hello world programs that demonstrate the different aspects of the basics of writing a kernel module.</para>
|
|
|
|
<para>Here's the simplest module possible. Don't compile it yet; we'll cover module compilation in the next section.</para>
|
|
|
|
<indexterm><primary>source file</primary><secondary>hello-1.c</secondary></indexterm>
|
|
|
|
|
|
<example><title>hello-1.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/hello-1.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
|
|
<indexterm><primary><function>init_module()</function></primary></indexterm>
|
|
<indexterm><primary><function>cleanup_module()</function></primary></indexterm>
|
|
|
|
<para>Kernel modules must have at least two functions: a "start" (initialization) function called
|
|
<function>init_module()</function> which is called when the module is insmoded into the kernel, and an "end" (cleanup)
|
|
function called <function>cleanup_module()</function> which is called just before it is rmmoded. Actually, things have
|
|
changed starting with kernel 2.3.13. You can now use whatever name you like for the start and end functions of a module, and
|
|
you'll learn how to do this in <xref linkend="hello2">. In fact, the new method is the preferred method. However, many
|
|
people still use <function>init_module()</function> and <function>cleanup_module()</function> for their start and end
|
|
functions.</para>
|
|
|
|
<para>Typically, <function>init_module()</function> either registers a handler for something with the kernel, or it replaces
|
|
one of the kernel functions with its own code (usually code to do something and then call the original function). The
|
|
<function>cleanup_module()</function> function is supposed to undo whatever <function>init_module()</function> did, so the
|
|
module can be unloaded safely.</para>
|
|
|
|
<para>Lastly, every kernel module needs to include <filename role="headerfile">linux/module.h</filename>. We needed to
|
|
include <filename role="headerfile">linux/kernel.h</filename> only for the macro expansion for the
|
|
<function>printk()</function> log level, <varname>KERN_ALERT</varname>, which you'll learn about in <xref
|
|
linkend="introducingprintk">.</para>
|
|
|
|
|
|
|
|
<sect2 id="introducingprintk"><title>Introducing <function>printk()</function></title>
|
|
|
|
<indexterm><primary><function>printk()</function></primary></indexterm>
|
|
<indexterm><primary><varname>DEFAULT_MESSAGE_LOGLEVEL</varname></primary></indexterm>
|
|
|
|
<para>Despite what you might think, <function>printk()</function> was not meant to communicate information to the user,
|
|
even though we used it for exactly this purpose in <application>hello-1</application>! It happens to be a logging
|
|
mechanism for the kernel, and is used to log information or give warnings. Therefore, each <function>printk()</function>
|
|
statement comes with a priority, which is the <varname><1></varname> and <varname>KERN_ALERT</varname> you see.
|
|
There are 8 priorities and the kernel has macros for them, so you don't have to use cryptic numbers, and you can view them
|
|
(and their meanings) in <filename role="headerfile">linux/kernel.h</filename>. If you don't specify a priority level, the
|
|
default priority, <literal>DEFAULT_MESSAGE_LOGLEVEL</literal>, will be used.</para>
|
|
|
|
<para>Take time to read through the priority macros. The header file also describes what each priority means. In
|
|
practise, don't use number, like <literal><4></literal>. Always use the macro, like
|
|
<literal>KERN_WARNING</literal>.</para>
|
|
|
|
<para>If the priority is less than <varname>int console_loglevel</varname>, the message is printed on your current
|
|
terminal. If both <command>syslogd</command> and <application>klogd</application> are running, then the message will also
|
|
get appended to <filename>/var/log/messages</filename>, whether it got printed to the console or not. We use a high
|
|
priority, like <literal>KERN_ALERT</literal>, to make sure the <function>printk()</function> messages get printed to your
|
|
console rather than just logged to your logfile. When you write real modules, you'll want to use priorities that are
|
|
meaningful for the situation at hand.</para>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
|
|
<sect1><title>Compiling Kernel Modules</title>
|
|
|
|
<indexterm><primary>insmod</primary></indexterm>
|
|
|
|
<para>Kernel modules need to be compiled a bit differently from regular userspace apps. Former kernel versions required us
|
|
to care much about these settings, which are usually stored in Makefiles. Although hierarchically organized, many redundant
|
|
settings accumulated in sublevel Makefiles and made them large and rather difficult to maintain.
|
|
|
|
Fortunately, there is a new way of doing these things, called kbuild, and the build process for external loadable modules
|
|
is now fully integrated into the standard kernel build mechanism. To learn more on how to compile modules which are not
|
|
part of the official kernel (such as all the examples you'll find in this guide), see file
|
|
<filename>linux/Documentation/kbuild/modules.txt</filename>.</para>
|
|
|
|
<para>So, let's look at a simple Makefile for compiling a module named <filename>hello-1.c</filename>:</para>
|
|
|
|
<example><title>Makefile for a basic kernel module</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/Makefile.1" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
<para>From a technical point of view just the first line is really necessary,
|
|
the "all" and "clean" targets were added for pure convenience.</para>
|
|
|
|
<para>Now you can compile the module by issuing the command <command> make </command>.
|
|
You should obtain an output which resembles the following:</para>
|
|
|
|
<screen>
|
|
hostname:~/lkmpg-examples/02-HelloWorld# make
|
|
make -C /lib/modules/2.6.11/build M=/root/lkmpg-examples/02-HelloWorld modules
|
|
make[1]: Entering directory `/usr/src/linux-2.6.11'
|
|
CC [M] /root/lkmpg-examples/02-HelloWorld/hello-1.o
|
|
Building modules, stage 2.
|
|
MODPOST
|
|
CC /root/lkmpg-examples/02-HelloWorld/hello-1.mod.o
|
|
LD [M] /root/lkmpg-examples/02-HelloWorld/hello-1.ko
|
|
make[1]: Leaving directory `/usr/src/linux-2.6.11'
|
|
hostname:~/lkmpg-examples/02-HelloWorld#
|
|
</screen>
|
|
|
|
<para>Note that kernel 2.6 introduces a new file naming convention: kernel modules now have a <filename>.ko</filename>
|
|
extension (in place of the old <filename>.o</filename> extension) which easily distinguishes them from conventional object
|
|
files. The reason for this is that they contain an additional .modinfo section that where additional information about the
|
|
module is kept. We'll soon see what this information is good for. </para>
|
|
|
|
<para> Use <command> modinfo hello-*.ko </command> to see what kind of information it is. </para>
|
|
|
|
<screen>
|
|
hostname:~/lkmpg-examples/02-HelloWorld# modinfo hello-1.ko
|
|
filename: hello-1.ko
|
|
vermagic: 2.6.11 preempt PENTIUMII 4KSTACKS gcc-3.3
|
|
depends:
|
|
</screen>
|
|
|
|
<para> Nothing spectacular, so far. That changes once we're using modinfo on one of our the later examples,
|
|
<filename> hello-5.ko </filename>. </para>
|
|
|
|
<screen>
|
|
hostname:~/lkmpg-examples/02-HelloWorld# modinfo hello-5.ko
|
|
filename: hello-5.ko
|
|
license: GPL
|
|
author: Peter Jay Salzman
|
|
vermagic: 2.6.11 preempt PENTIUMII 4KSTACKS gcc-3.3
|
|
depends:
|
|
parm: myintArray:An array of integers (array of int)
|
|
parm: mystring:A character string (charp)
|
|
parm: mylong:A long integer (long)
|
|
parm: myint:An integer (int)
|
|
parm: myshort:A short integer (short)
|
|
hostname:~/lkmpg-examples/02-HelloWorld#
|
|
</screen>
|
|
|
|
<para> Lot's of useful information to see here. An author string for bugreports,
|
|
license information, even a short description of the parameters it accepts. </para>
|
|
|
|
<para> Additional details about Makefiles for kernel modules are available in
|
|
<filename>linux/Documentation/kbuild/makefiles.txt</filename>.
|
|
Be sure to read this and the related files before starting to hack Makefiles.
|
|
It'll probably save you lots of work. </para>
|
|
|
|
<para>Now it is time to insert your freshly-compiled module it into the kernel with <command>insmod ./hello-1.ko</command>
|
|
(ignore anything you see about tainted kernels; we'll cover that shortly).</para>
|
|
|
|
<para>
|
|
All modules loaded into the kernel are listed in <filename>/proc/modules</filename>.
|
|
Go ahead and cat that file to see that your module is really a part of the kernel.
|
|
Congratulations, you are now the author of Linux kernel code! When the novelty wears off,
|
|
remove your module from the kernel by using <command>rmmod hello-1</command>. Take a look at
|
|
<filename>/var/log/messages</filename> just to see that it got logged to your system logfile.</para>
|
|
|
|
<para>Here's another exercise for the reader. See that comment above the return statement in
|
|
<function>init_module()</function>? Change the return value to something negative, recompile and load the module again.
|
|
What happens?</para>
|
|
|
|
</sect1>
|
|
|
|
|
|
<sect1 id="hello2"><title>Hello World (part 2)</title>
|
|
|
|
<indexterm><primary>module_init</primary></indexterm>
|
|
<indexterm><primary>module_exit</primary></indexterm>
|
|
|
|
<para>As of Linux 2.4, you can rename the init and cleanup functions of your modules; they no longer have to be called
|
|
<function>init_module()</function> and <function>cleanup_module()</function> respectively. This is done with the
|
|
<function>module_init()</function> and <function>module_exit()</function> macros. These macros are defined in <filename
|
|
role="header">linux/init.h</filename>. The only caveat is that your init and cleanup functions must be defined before
|
|
calling the macros, otherwise you'll get compilation errors. Here's an example of this technique:</para>
|
|
|
|
<indexterm><primary>source file</primary><secondary>hello-2.c</secondary></indexterm>
|
|
|
|
|
|
<example><title>hello-2.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/hello-2.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
|
|
<para>So now we have two real kernel modules under our belt. Adding another module is as simple as this: </para>
|
|
|
|
|
|
<example><title>Makefile for both our modules</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/Makefile.2" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
|
|
<para>Now have a look at <filename>linux/drivers/char/Makefile</filename> for a real world example. As you can see, some things
|
|
get hardwired into the kernel (obj-y) but where are all those obj-m gone? Those familiar with shell scripts will easily be
|
|
able to spot them. For those not, the obj-$(CONFIG_FOO) entries you see everywhere expand into obj-y or obj-m, depending on
|
|
whether the CONFIG_FOO variable has been set to y or m. While we are at it, those were exactly the kind of variables
|
|
that you have set in the <filename>linux/.config</filename> file, the last time when you said <command>make menuconfig</command>
|
|
or something like that.
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
|
|
<sect1><title>Hello World (part 3): The <literal>__init</literal> and <literal>__exit</literal> Macros</title>
|
|
|
|
<indexterm><primary><function>__init</function></primary></indexterm>
|
|
<indexterm><primary><function>__initdata</function></primary></indexterm>
|
|
<indexterm><primary><function>__exit</function></primary></indexterm>
|
|
<indexterm><primary><function>__initfunction()</function></primary></indexterm>
|
|
|
|
<para>This demonstrates a feature of kernel 2.2 and later. Notice the change in the definitions of the init and cleanup
|
|
functions. The <function>__init</function> macro causes the init function to be discarded and its memory freed once the init
|
|
function finishes for built-in drivers, but not loadable modules. If you think about when the init function is invoked, this
|
|
makes perfect sense.</para>
|
|
|
|
<para>There is also an <function>__initdata</function> which works similarly to <function>__init</function> but for init
|
|
variables rather than functions.</para>
|
|
|
|
<para>The <function>__exit</function> macro causes the omission of the function when the module is built into the kernel, and
|
|
like <function>__exit</function>, has no effect for loadable modules. Again, if you consider when the cleanup function runs,
|
|
this makes complete sense; built-in drivers don't need a cleanup function, while loadable modules do.</para>
|
|
|
|
<para>These macros are defined in <filename role="headerfile">linux/init.h</filename> and serve to free up kernel memory.
|
|
When you boot your kernel and see something like <literal>Freeing unused kernel memory: 236k freed</literal>, this is
|
|
precisely what the kernel is freeing.</para>
|
|
|
|
<indexterm><primary>source file</primary><secondary>hello-3.c</secondary></indexterm>
|
|
|
|
|
|
<example><title>hello-3.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/hello-3.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
</sect1>
|
|
|
|
|
|
<sect1><title>Hello World (part 4): Licensing and Module Documentation</title>
|
|
|
|
<para>If you're running kernel 2.4 or later, you might have noticed something like this when you loaded proprietary modules:</para>
|
|
|
|
<screen>
|
|
# insmod xxxxxx.o
|
|
Warning: loading xxxxxx.ko will taint the kernel: no license
|
|
See http://www.tux.org/lkml/#export-tainted for information about tainted modules
|
|
Module xxxxxx loaded, with warnings
|
|
</screen>
|
|
|
|
<indexterm><primary><function>MODULE_LICENSE()</function></primary></indexterm>
|
|
|
|
<para>In kernel 2.4 and later, a mechanism was devised to identify code licensed under the GPL (and friends) so people can
|
|
be warned that the code is non open-source. This is accomplished by the <function>MODULE_LICENSE()</function> macro which
|
|
is demonstrated in the next piece of code. By setting the license to GPL, you can keep the warning from being printed.
|
|
This license mechanism is defined and documented in <filename role="headerfile">linux/module.h</filename>:
|
|
|
|
<screen>
|
|
/*
|
|
* The following license idents are currently accepted as indicating free
|
|
* software modules
|
|
*
|
|
* "GPL" [GNU Public License v2 or later]
|
|
* "GPL v2" [GNU Public License v2]
|
|
* "GPL and additional rights" [GNU Public License v2 rights and more]
|
|
* "Dual BSD/GPL" [GNU Public License v2
|
|
* or BSD license choice]
|
|
* "Dual MIT/GPL" [GNU Public License v2
|
|
* or MIT license choice]
|
|
* "Dual MPL/GPL" [GNU Public License v2
|
|
* or Mozilla license choice]
|
|
*
|
|
* The following other idents are available
|
|
*
|
|
* "Proprietary" [Non free products]
|
|
*
|
|
* There are dual licensed components, but when running with Linux it is the
|
|
* GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
|
|
* is a GPL combined work.
|
|
*
|
|
* This exists for several reasons
|
|
* 1. So modinfo can show license info for users wanting to vet their setup
|
|
* is free
|
|
* 2. So the community can ignore bug reports including proprietary modules
|
|
* 3. So vendors can do likewise based on their own policies
|
|
*/
|
|
</screen>
|
|
</para>
|
|
|
|
<indexterm><primary><function>MODULE_DESCRIPTION()</function></primary></indexterm>
|
|
<indexterm><primary><function>MODULE_AUTHOR()</function></primary></indexterm>
|
|
<indexterm><primary><function>MODULE_SUPPORTED_DEVICE()</function></primary></indexterm>
|
|
|
|
<para>Similarly, <function>MODULE_DESCRIPTION()</function> is used to describe what the module does,
|
|
<function>MODULE_AUTHOR()</function> declares the module's author, and <function>MODULE_SUPPORTED_DEVICE()</function>
|
|
declares what types of devices the module supports.</para>
|
|
|
|
<para>These macros are all defined in <filename role="headerfile">linux/module.h</filename> and aren't used by the kernel
|
|
itself. They're simply for documentation and can be viewed by a tool like <application>objdump</application>.
|
|
As an exercise to the reader, try and search fo these macros in <filename role="directory">linux/drivers</filename>
|
|
to see how module authors use these macros to document their modules.</para>
|
|
|
|
<para> I'd recommend to use something like <command> grep -inr MODULE_AUTHOR * </command> in
|
|
<filename> /usr/src/linux-2.6.x/ </filename>. People unfamiliar with command line tools will probably like
|
|
some web base solution, search for sites that offer kernel trees that got indexed with LXR. (or setup it up on your
|
|
local machine).</para>
|
|
|
|
<para> Users of traditional Unix editors, like <command> emacs </command> or <command> vi </command> will also find
|
|
tag files useful. They can be generated by <command> make tags </command> or <command> make TAGS </command> in
|
|
<filename> /usr/src/linux-2.6.x/ </filename>. Once you've got such a tagfile in your kerneltree you can put the cursor
|
|
on some function call and use some key combination to directly jump to the definition function. </para>
|
|
|
|
<indexterm><primary>source file</primary><secondary>hello-4.c</secondary></indexterm>
|
|
|
|
|
|
<example><title>hello-4.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/hello-4.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
|
|
<sect1><title>Passing Command Line Arguments to a Module</title>
|
|
|
|
<para>Modules can take command line arguments, but not with the <varname>argc</varname>/<varname>argv</varname> you might be
|
|
used to.</para>
|
|
|
|
<para>To allow arguments to be passed to your module, declare the variables that will take the values of the command line
|
|
arguments as global and then use the <functioN>module_param()</function> macro, (defined in <filename
|
|
role="headerfile">linux/moduleparam.h</filename>) to set the mechanism up. At runtime, insmod will fill the variables with any
|
|
command line arguments that are given, like <command>./insmod mymodule.ko myvariable=5</command>. The variable
|
|
declarations and macros should be placed at the beginning of the module for clarity. The example code should clear up my
|
|
admittedly lousy explanation.</para>
|
|
|
|
<para>The <function>module_param()</function> macro takes 3 arguments: the name of the variable, its type and
|
|
permissions for the corresponding file in sysfs. Integer types can be signed as usual or unsigned.
|
|
If you'd like to use arrays of integers or strings see <function>module_param_array()</function> and
|
|
<function>module_param_string()</function>.</para>
|
|
|
|
|
|
<screen>
|
|
int myint = 3;
|
|
module_param(myint, int, 0);
|
|
</screen>
|
|
|
|
<para>Arrays are supported too, but things are a bit different now than they were in the 2.4. days. To keep track of the
|
|
number of parameters you need to pass a pointer to a count variable as third parameter. At your option, you could also
|
|
ignore the count and pass NULL instead. We show both possibilities here:</para>
|
|
|
|
<screen>
|
|
int myintarray[2];
|
|
module_param_array(myintarray, int, NULL, 0); /* not interested in count */
|
|
|
|
int myshortarray[4];
|
|
int count;
|
|
module_parm_array(myshortarray, short, &count, 0); /* put count into "count" variable */
|
|
</screen>
|
|
|
|
<para>A good use for this is to have the module variable's default values set, like an port or IO address. If the variables
|
|
contain the default values, then perform autodetection (explained elsewhere). Otherwise, keep the current value. This will
|
|
be made clear later on.</para>
|
|
|
|
<para>Lastly, there's a macro function, <function>MODULE_PARM_DESC()</function>, that is used to document arguments that the
|
|
module can take. It takes two parameters: a variable name and a free form string describing that variable.</para>
|
|
|
|
<indexterm><primary>source file</primary><secondary>hello-5.c</secondary></indexterm>
|
|
|
|
|
|
<example><title>hello-5.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/hello-5.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
|
|
<para>I would recommend playing around with this code:</para>
|
|
|
|
<screen>
|
|
satan# insmod hello-5.ko mystring="bebop" mybyte=255 myintArray=-1
|
|
mybyte is an 8 bit integer: 255
|
|
myshort is a short integer: 1
|
|
myint is an integer: 20
|
|
mylong is a long integer: 9999
|
|
mystring is a string: bebop
|
|
myintArray is -1 and 420
|
|
|
|
satan# rmmod hello-5
|
|
Goodbye, world 5
|
|
|
|
satan# insmod hello-5.ko mystring="supercalifragilisticexpialidocious" \
|
|
> mybyte=256 myintArray=-1,-1
|
|
mybyte is an 8 bit integer: 0
|
|
myshort is a short integer: 1
|
|
myint is an integer: 20
|
|
mylong is a long integer: 9999
|
|
mystring is a string: supercalifragilisticexpialidocious
|
|
myintArray is -1 and -1
|
|
|
|
satan# rmmod hello-5
|
|
Goodbye, world 5
|
|
|
|
satan# insmod hello-5.ko mylong=hello
|
|
hello-5.o: invalid argument syntax for mylong: 'h'
|
|
</screen>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
|
|
|
|
<sect1><title>Modules Spanning Multiple Files</title>
|
|
|
|
<indexterm><primary>source files</primary><secondary>multiple</secondary></indexterm>
|
|
|
|
<para>Sometimes it makes sense to divide a kernel module between several source files.</para>
|
|
|
|
<para>Here's an example of such a kernel module.</para>
|
|
|
|
<indexterm><primary>source file</primary><secondary>start.c</secondary></indexterm>
|
|
|
|
<example><title>start.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/start.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
<para>The next file:</para>
|
|
|
|
<indexterm><primary>source file</primary><secondary>stop.c</secondary></indexterm>
|
|
|
|
|
|
<example><title>stop.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/stop.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
<para>And finally, the makefile:</para>
|
|
|
|
|
|
<example><title>Makefile</title><programlisting><inlinegraphic fileref="lkmpg-examples/02-HelloWorld/Makefile" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
<para>This is the complete makefile for all the examples we've seen so far. The first five lines are nothing special,
|
|
but for the last example we'll need two lines. First we invent an object name for our combined module, second we tell
|
|
<command> make </command> what object files are part of that module. </para>
|
|
|
|
</sect1>
|
|
|
|
<sect1><title>Building modules for a precompiled kernel</title>
|
|
|
|
<indexterm><primary>source files</primary><secondary>multiple</secondary></indexterm>
|
|
|
|
<para>
|
|
Obviously, we strongly suggest you to recompile your kernel, so that you can enable a number of useful debugging features, such as
|
|
forced module unloading (<literal>MODULE_FORCE_UNLOAD</literal>): when this option is enabled, you can force the kernel to unload a module even
|
|
when it believes it is unsafe, via a <command>rmmod -f module</command> command. This option can save you a lot of time and a number of reboots
|
|
during the development of a module.
|
|
</para>
|
|
|
|
<para>
|
|
Nevertheless, there is a number of cases in which you may want to load your module into a precompiled running kernel, such as the ones shipped
|
|
with common Linux distributions, or a kernel you have compiled in the past. In certain circumstances you could require to compile and insert a
|
|
module into a running kernel which you are not allowed to recompile, or on a machine that you prefer not to reboot.
|
|
If you can't think of a case that will force you to use modules for a precompiled kernel you
|
|
might want to skip this and treat the rest of this chapter as a big footnote.
|
|
</para>
|
|
|
|
<para>
|
|
Now, if you just install a kernel source tree, use it to compile your kernel module and you try to insert your module into the kernel,
|
|
in most cases you would obtain an error as follows:
|
|
</para>
|
|
|
|
<screen>
|
|
insmod: error inserting 'poet_atkm.ko': -1 Invalid module format
|
|
</screen>
|
|
|
|
<para>
|
|
Less cryptical information are logged to <filename>/var/log/messages</filename>:
|
|
</para>
|
|
|
|
<screen>
|
|
Jun 4 22:07:54 localhost kernel: poet_atkm: version magic '2.6.5-1.358custom 686
|
|
REGPARM 4KSTACKS gcc-3.3' should be '2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3'
|
|
</screen>
|
|
|
|
<para>
|
|
In other words, your kernel refuses to accept your module because version strings (more precisely, version magics)
|
|
do not match. Incidentally, version magics are stored in the module object in the form of a static string, starting with
|
|
<literal>vermagic:</literal>.
|
|
Version data are inserted in your module when it is linked against the <filename>init/vermagic.o</filename> file.
|
|
To inspect version magics and other strings stored in a given module, issue the
|
|
<command>modinfo module.ko</command> command:
|
|
</para>
|
|
|
|
<screen>
|
|
[root@pcsenonsrv 02-HelloWorld]# modinfo hello-4.ko
|
|
license: GPL
|
|
author: Peter Jay Salzman <p@dirac.org>
|
|
description: A sample driver
|
|
vermagic: 2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3
|
|
depends:
|
|
</screen>
|
|
|
|
<para>
|
|
To overcome this problem we could resort to the <command>--force-vermagic</command> option, but this solution is potentially unsafe,
|
|
and unquestionably inacceptable in production modules.
|
|
Consequently, we want to compile our module in an environment which was identical to the one in which our precompiled kernel was built.
|
|
How to do this, is the subject of the remainder of this chapter.</para>
|
|
|
|
<para>
|
|
First of all, make sure that a kernel source tree is available, having exactly the same version as
|
|
your current kernel. Then, find the configuration file which was used to compile your precompiled kernel.
|
|
Usually, this is available in your current <filename>/boot</filename> directory, under a name like <filename>config-2.6.x</filename>.
|
|
You may just want to copy it to your kernel source tree:
|
|
<command> cp /boot/config-`uname -r` /usr/src/linux-`uname -r`/.config</command>. </para>
|
|
|
|
<para>
|
|
Let's focus again on the previous error message: a closer look at the version magic strings suggests that, even with two configuration files
|
|
which are exactly the same, a slight difference in the version magic could be possible, and it is sufficient to prevent insertion of the module
|
|
into the kernel.
|
|
That slight difference, namely the <literal>custom</literal> string which appears in the module's version magic and not in the kernel's one,
|
|
is due to a modification with respect to the original, in the makefile that some distribution include.
|
|
Then, examine your <filename>/usr/src/linux/Makefile</filename>, and make sure that the specified version information matches exactly the one used
|
|
for your current kernel. For example, you makefile could start as follows: </para>
|
|
|
|
<screen>
|
|
VERSION = 2
|
|
PATCHLEVEL = 6
|
|
SUBLEVEL = 5
|
|
EXTRAVERSION = -1.358custom
|
|
...
|
|
</screen>
|
|
|
|
<para>
|
|
In this case, you need to restore the value of symbol <literal>EXTRAVERSION</literal> to <literal>-1.358</literal>.
|
|
We suggest to keep a backup copy of the makefile used to compile your kernel available in <filename>/lib/modules/2.6.5-1.358/build</filename>.
|
|
A simple <command>cp /lib/modules/`uname -r`/build/Makefile /usr/src/linux-`uname -r`</command> should suffice.
|
|
Additionally, if you already started a kernel build with the previous (wrong) <filename>Makefile</filename>,
|
|
you should also rerun <command>make</command>, or directly modify symbol <literal>UTS_RELEASE</literal> in file
|
|
<filename>/usr/src/linux-2.6.x/include/linux/version.h</filename> according to contents of file
|
|
<filename>/lib/modules/2.6.x/build/include/linux/version.h</filename>, or overwrite the latter with the first.
|
|
</para>
|
|
|
|
<para>
|
|
Now, please run <command>make</command> to update configuration and version headers and objects:
|
|
</para>
|
|
<screen>
|
|
[root@pcsenonsrv linux-2.6.x]# make
|
|
CHK include/linux/version.h
|
|
UPD include/linux/version.h
|
|
SYMLINK include/asm -> include/asm-i386
|
|
SPLIT include/linux/autoconf.h -> include/config/*
|
|
HOSTCC scripts/basic/fixdep
|
|
HOSTCC scripts/basic/split-include
|
|
HOSTCC scripts/basic/docproc
|
|
HOSTCC scripts/conmakehash
|
|
HOSTCC scripts/kallsyms
|
|
CC scripts/empty.o
|
|
...
|
|
</screen>
|
|
<para>
|
|
If you do not desire to actually compile the kernel, you can interrupt the build process (<command>CTRL-C</command>) just after the
|
|
<literal>SPLIT</literal> line, because at that time, the files you need will be are ready.
|
|
Now you can turn back to the directory of your module and compile it: It will be built exactly according your current kernel settings,
|
|
and it will load into it without any errors.
|
|
</para>
|
|
</sect1>
|
|
|
|
<!--
|
|
vim: tw=128
|
|
-->
|
|
|