mirror of https://github.com/tLDP/LDP
171 lines
9.0 KiB
Plaintext
171 lines
9.0 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/modules.conf</filename>. 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.o</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.o</filename> requires the <filename>fat.o</filename> module to be already
|
|
loaded into the kernel. The requested module has a dependancy 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. So for example,
|
|
if you wanted to load the msdos module, you'd have to either run:</para>
|
|
|
|
<screen>
|
|
insmod /lib/modules/2.5.1/kernel/fs/fat/fat.o
|
|
insmod /lib/modules/2.5.1/kernel/fs/msdos/msdos.o
|
|
</screen>
|
|
|
|
<para>or just run "<command>modprobe -a msdos</command>".</para>
|
|
|
|
<indexterm><primary>modules.conf</primary><secondary>keep</secondary></indexterm>
|
|
<indexterm><primary>modules.conf</primary><secondary>comment</secondary></indexterm>
|
|
<indexterm><primary>modules.conf</primary><secondary>alias</secondary></indexterm>
|
|
<indexterm><primary>modules.conf</primary><secondary>options</secondary></indexterm>
|
|
<indexterm><primary>modules.conf</primary><secondary>path</secondary></indexterm>
|
|
|
|
|
|
<para>Linux distros provide modprobe, insmod and depmod as a package called modutils or mod-utils.</para>
|
|
|
|
<para>Before finishing this chapter, let's take a quick look at a piece of <filename>/etc/modules.conf</filename>:</para>
|
|
|
|
<screen>
|
|
#This file is automatically generated by update-modules
|
|
path[misc]=/lib/modules/2.4.?/local
|
|
keep
|
|
path[net]=~p/mymodules
|
|
options mydriver irq=10
|
|
alias eth0 eepro
|
|
</screen>
|
|
|
|
<para>Lines beginning with a '#' are comments. Blank lines are ignored.</para>
|
|
|
|
<para>The <literal>path[misc]</literal> line tells modprobe to replace the search path for misc modules with the directory
|
|
<filename role="directory">/lib/modules/2.4.?/local</filename>. As you can see, shell meta characters are honored.</para>
|
|
|
|
<para>The <literal>path[net]</literal> line tells modprobe to look for net modules in the directory <filename
|
|
role="directory">~p/mymodules</filename>, however, the "keep" directive preceding the <literal>path[net]</literal> directive
|
|
tells modprobe to add this directory to the standard search path of net modules as opposed to replacing the standard search
|
|
path, as we did for the misc modules.</para>
|
|
|
|
<para>The alias line says to load in <filename>eepro.o</filename> whenever kmod requests that the generic identifier `eth0' be
|
|
loaded.</para>
|
|
|
|
<para>You won't see lines like "alias block-major-2 floppy" in <filename>/etc/modules.conf</filename> because modprobe already
|
|
knows about the standard drivers which will be used on most systems.</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 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
|
|
-->
|