mirror of https://github.com/tLDP/LDP
154 lines
8.5 KiB
Plaintext
154 lines
8.5 KiB
Plaintext
<sect1><title>What Is A Kernel Module?</title>
|
|
|
|
<para>So, you want to write a kernel module. You know C, you've written a few normal programs to run as processes, and now
|
|
you want to get to where the real action is, to where a single wild pointer can wipe out your file system and a core dump
|
|
means a reboot.</para>
|
|
|
|
<para>What exactly is a kernel module? Modules are pieces of code that can be loaded and unloaded into the kernel upon
|
|
demand. They extend the functionality of the kernel without the need to reboot the system. For example, one type of module
|
|
is the device driver, which allows the kernel to access hardware connected to the system. Without modules, we would have to
|
|
build monolithic kernels and add new functionality directly into the kernel image. Besides having larger kernels, this has
|
|
the disadvantage of requiring us to rebuild and reboot the kernel every time we want new functionality.</para>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<sect1><title>How Do Modules Get Into The Kernel?</title>
|
|
|
|
<indexterm><primary>/proc/modules</primary></indexterm>
|
|
<indexterm><primary>kmod</primary></indexterm>
|
|
<indexterm><primary>kerneld</primary></indexterm>
|
|
<indexterm><primary><filename>/etc/modules.conf</filename></primary></indexterm>
|
|
<indexterm><primary><filename>/etc/conf.modules</filename></primary></indexterm>
|
|
|
|
<para>You can see what modules are already loaded into the kernel by running <command>lsmod</command>, which gets its
|
|
information by reading the file <filename>/proc/modules</filename>.</para>
|
|
|
|
<para>How do these modules find their way into the kernel? When the kernel needs a feature that is not resident in the
|
|
kernel, the kernel module daemon kmod<footnote><para>In earlier versions of linux, this was known as
|
|
kerneld.</para></footnote> execs modprobe to load the module in. modprobe is passed a string in one of two forms:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>A module name like <filename>softdog</filename> or <filename>ppp</filename>.</para></listitem>
|
|
<listitem><para>A more generic identifier like <varname>char-major-10-30</varname>.</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>If modprobe is handed a generic identifier, it first looks for that string in the file
|
|
<filename>/etc/modprobe.conf</filename>.<footnote><para>If such a file exists. Note that the acual behavoir might be
|
|
distribution-dependent. If you're interested in the details,read the man pages that came with module-init-tools,
|
|
and see for yourself what's really going on. You could use something like <command> strace modprobe dummy </command>
|
|
to find out how dummy.ko gets loaded. FYI: The dummy.ko I'm talking about here is part of the mainline kernel
|
|
and can be found in the networking section. It needs to be compiled as a module (and installed, of course) for this to
|
|
work. </para></footnote>
|
|
If it finds an alias line like:</para>
|
|
|
|
<screen>
|
|
alias char-major-10-30 softdog
|
|
</screen>
|
|
|
|
<para>it knows that the generic identifier refers to the module <filename>softdog.ko</filename>.</para>
|
|
|
|
<para>Next, modprobe looks through the file <filename>/lib/modules/version/modules.dep</filename>, to see if other modules
|
|
must be loaded before the requested module may be loaded. This file is created by <command>depmod -a</command> and
|
|
contains module dependencies. For example, <filename>msdos.ko</filename> requires the <filename>fat.ko</filename> module
|
|
to be already loaded into the kernel. The requested module has a dependency on another module if the other module defines
|
|
symbols (variables or functions) that the requested module uses.</para>
|
|
|
|
<para>Lastly, modprobe uses insmod to first load any prerequisite modules into the kernel, and then the requested module.
|
|
modprobe directs insmod to <filename role="directory">/lib/modules/version/</filename><footnote><para>If you are modifying
|
|
the kernel, to avoid overwriting your existing modules you may want to use the <varname>EXTRAVERSION</varname> variable in
|
|
the kernel Makefile to create a seperate directory.</para></footnote>, the standard directory for modules. insmod is
|
|
intended to be fairly dumb about the location of modules, whereas modprobe is aware of the default location of modules,
|
|
knows how to figure out the dependencies and load the modules in the right order.
|
|
So for example, if you wanted to load the msdos module, you'd have to either run:</para>
|
|
|
|
<screen>
|
|
insmod /lib/modules/2.6.11/kernel/fs/fat/fat.ko
|
|
insmod /lib/modules/2.6.11/kernel/fs/msdos/msdos.ko
|
|
</screen>
|
|
|
|
<para> or: </para>
|
|
<screen>
|
|
modprobe msdos
|
|
</screen>
|
|
|
|
<para> What we've seen here is: <command> insmod </command> requires you to pass it the full pathname and to insert the modules
|
|
in the right order, while <command> modprobe </command> just takes the name, without any extension, and figures out
|
|
all it needs to know by parsing <filename>/lib/modules/version/modules.dep</filename>.</para>
|
|
|
|
<para>Linux distros provide modprobe, insmod and depmod as a package called module-init-tools. In previous versions
|
|
that package was called modutils. Some distros also set up some wrappers that allow both packages to be installed
|
|
in parallel and do the right thing in order to be able to deal with 2.4 and 2.6 kernels. Users should not need to care
|
|
about the details, as long as they're running recent versions of those tools.</para>
|
|
|
|
<para>Now you know how modules get into the kernel. There's a bit more to the story if you want to write your own modules
|
|
which depend on other modules (we calling this `stacking modules'). But this will have to wait for a future chapter.
|
|
We have a lot to cover before addressing this relatively high-level issue.</para>
|
|
|
|
|
|
|
|
<sect2><title>Before We Begin</title>
|
|
|
|
<para>Before we delve into code, there are a few issues we need to cover. Everyone's system is different and everyone has
|
|
their own groove. Getting your first "hello world" program to compile and load correctly can sometimes be a trick. Rest
|
|
assured, after you get over the initial hurdle of doing it for the first time, it will be smooth sailing
|
|
thereafter.</para>
|
|
|
|
|
|
|
|
<sect3><title>Modversioning</title>
|
|
|
|
<para>A module compiled for one kernel won't load if you boot a different kernel unless you enable
|
|
<literal>CONFIG_MODVERSIONS</literal> in the kernel. We won't go into module versioning until later in this guide.
|
|
Until we cover modversions, the examples in the guide may not work if you're running a kernel with modversioning
|
|
turned on. However, most stock Linux distro kernels come with it turned on. If you're having trouble loading the
|
|
modules because of versioning errors, compile a kernel with modversioning turned off.</para>
|
|
|
|
</sect3>
|
|
|
|
|
|
|
|
<sect3 id="usingx"><title>Using X</title>
|
|
|
|
<para>It is highly recommended that you type in, compile and load all the examples this guide discusses. It's also
|
|
highly recommended you do this from a console. You should not be working on this stuff in X.</para>
|
|
|
|
<para>Modules can't print to the screen like <function>printf()</function> can, but they can log information and
|
|
warnings, which ends up being printed on your screen, but only on a console. If you insmod a module from an xterm,
|
|
the information and warnings will be logged, but only to your log files. You won't see it unless you look through
|
|
your log files. To have immediate access to this information, do all your work from the console.</para>
|
|
|
|
</sect3>
|
|
|
|
|
|
|
|
<sect3><title>Compiling Issues and Kernel Version</title>
|
|
|
|
<para>Very often, Linux distros will distribute kernel source that has been patched in various non-standard ways,
|
|
which may cause trouble.</para>
|
|
|
|
<para>A more common problem is that some Linux distros distribute incomplete kernel headers. You'll need to compile
|
|
your code using various header files from the Linux kernel. Murphy's Law states that the headers that are missing are
|
|
exactly the ones that you'll need for your module work.</para>
|
|
|
|
<para>To avoid these two problems, I highly recommend that you download, compile and boot into a fresh, stock Linux
|
|
kernel which can be downloaded from any of the Linux kernel mirror sites. See the Linux Kernel HOWTO for more
|
|
details.</para>
|
|
|
|
<para>Ironically, this can also cause a problem. By default, gcc on your system may look for the kernel headers in
|
|
their default location rather than where you installed the new copy of the kernel (usually in <filename
|
|
role="directory">/usr/src/</filename>. This can be fixed by using gcc's <literal>-I</literal> switch.</para>
|
|
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<!--
|
|
vim: tw=128
|
|
-->
|