324 lines
16 KiB
HTML
324 lines
16 KiB
HTML
|
<HTML>
|
|||
|
<center>
|
|||
|
<A HREF="../tlk-toc.html"> Table of Contents</A>,
|
|||
|
<A href="../tlk.html" target="_top"> Show Frames</A>,
|
|||
|
<A href="../modules/modules.html" target="_top"> No Frames</A>
|
|||
|
</center>
|
|||
|
<hr>
|
|||
|
<META NAME="TtH" CONTENT="1.03">
|
|||
|
|
|||
|
<p>
|
|||
|
<H1><A NAME="tth_chAp12">Chapter 12 <br>Modules</H1>
|
|||
|
<A NAME="modules-chapter"></A>
|
|||
|
<p>
|
|||
|
<img src="../logos/sit3-bw-tran.1.gif"><br> <tt><b></tt></b>
|
|||
|
This chapter describes how the Linux kernel can dynamically load functions,
|
|||
|
for example filesystems, only when they are needed.
|
|||
|
|
|||
|
<p>
|
|||
|
Linux is a monolithic kernel;
|
|||
|
that is, it is one, single, large program
|
|||
|
where all the functional components of the kernel have access to all
|
|||
|
of its internal data structures and routines.
|
|||
|
The alternative is to have a micro-kernel structure where
|
|||
|
the functional pieces of the kernel are broken out into separate units
|
|||
|
with strict communication mechanisms between them.
|
|||
|
This makes adding new components into the kernel via the configuration
|
|||
|
process rather time consuming.
|
|||
|
Say you wanted to use a SCSI driver for an NCR 810 SCSI and you had
|
|||
|
not built it into the kernel.
|
|||
|
You would have to configure and then build a new kernel before you
|
|||
|
could use the NCR 810.
|
|||
|
There is an alternative, Linux allows you to dynamically load
|
|||
|
and unload components of the operating system as you need them.
|
|||
|
Linux modules are lumps of code that can be dynamically linked into the
|
|||
|
kernel at any point after the system has booted.
|
|||
|
They can be unlinked from the kernel and removed when they are no longer
|
|||
|
needed.
|
|||
|
Mostly Linux kernel modules are device drivers, pseudo-device drivers
|
|||
|
such as network drivers, or file-systems.
|
|||
|
|
|||
|
<p>
|
|||
|
You can either load and unload Linux kernel modules explicitly using
|
|||
|
the <font face="helvetica">insmod</font> and <font face="helvetica">rmmod</font> commands or the kernel itself can demand
|
|||
|
that the kernel daemon (<tt>kerneld</tt>) loads and unloads the modules as they are needed.
|
|||
|
|
|||
|
<p>
|
|||
|
Dynamically loading code as it is needed is attractive as it keeps the
|
|||
|
kernel size to a minimum and makes the kernel very flexible.
|
|||
|
My current Intel kernel uses modules extensively and is only 406Kbytes long.
|
|||
|
I only occasionally use <tt>VFAT</tt> file systems and so I build my Linux kernel
|
|||
|
to automatically load the <tt>VFAT</tt> file system module as I mount a <tt>VFAT</tt>
|
|||
|
partition.
|
|||
|
When I have unmounted the <tt>VFAT</tt> partition the system detects that I no
|
|||
|
longer need the <tt>VFAT</tt> file system module and removes it from the system.
|
|||
|
Modules can also be useful for trying out new kernel code without having
|
|||
|
to rebuild and reboot the kernel every time you try it out.
|
|||
|
Nothing, though, is for free and there is a slight performance and
|
|||
|
memory penalty associated with kernel modules.
|
|||
|
There is a little more code that a loadable module must provide
|
|||
|
and this and the extra data structures take a little more memory.
|
|||
|
There is also a level of indirection introduced that makes accesses of
|
|||
|
kernel resources slightly less efficient for modules.
|
|||
|
|
|||
|
<p>
|
|||
|
Once a Linux module has been loaded it is as much a part of the kernel
|
|||
|
as any normal kernel code.
|
|||
|
It has the same rights and responsibilities as any kernel code; in other
|
|||
|
words, Linux kernel modules can crash the kernel just like all kernel
|
|||
|
code or device drivers can.
|
|||
|
|
|||
|
<p>
|
|||
|
So that modules can use the kernel resources that they need, they must
|
|||
|
be able to find them.
|
|||
|
Say a module needs to call <tt>kmalloc()</tt>, the kernel memory allocation
|
|||
|
routine.
|
|||
|
At the time that it is built, a module does not know where in memory
|
|||
|
<tt>kmalloc()</tt> is, so when
|
|||
|
the module is loaded, the kernel must fix up all of the module's
|
|||
|
references to <tt>kmalloc()</tt> before the module can work.
|
|||
|
The kernel keeps a list of all of the kernel's resources in the kernel symbol
|
|||
|
table so that it can resolve references to those resources from the modules
|
|||
|
as they are loaded.
|
|||
|
Linux allows module stacking, this is where one module requires the
|
|||
|
services of another module.
|
|||
|
For example, the <tt>VFAT</tt> file system module requires the services
|
|||
|
of the <tt>FAT</tt> file system module as the <tt>VFAT</tt> file system is more
|
|||
|
or less a set of extensions to the <tt>FAT</tt> file system.
|
|||
|
One module requiring services or resources from another module is very
|
|||
|
similar to the situation where a module requires services and resources
|
|||
|
from the kernel itself.
|
|||
|
Only here the required services are in another, previously loaded
|
|||
|
module.
|
|||
|
As each module is loaded, the kernel modifies the kernel symbol table,
|
|||
|
adding to it all of the resources or symbols exported by the newly
|
|||
|
loaded module.
|
|||
|
This means that, when the next module is loaded, it has access to
|
|||
|
the services of the already loaded modules.
|
|||
|
|
|||
|
<p>
|
|||
|
When an attempt is made to unload a module, the kernel needs to know
|
|||
|
that the module is unused and it needs some way of notifying the module
|
|||
|
that it is about to be unloaded.
|
|||
|
That way the module will be able to free up any system resources that it
|
|||
|
has allocated, for example kernel memory or interrupts, before it is
|
|||
|
removed from the kernel.
|
|||
|
When the module is unloaded, the kernel removes any symbols that that module
|
|||
|
exported into the kernel symbol table.
|
|||
|
|
|||
|
<p>
|
|||
|
Apart from the ability of a loaded module to crash the operating system
|
|||
|
by being badly written, it presents another danger.
|
|||
|
What happens if you load a module built for an earlier or later kernel
|
|||
|
than the one that you are now running?
|
|||
|
This may cause a problem if, say, the module makes a call to a kernel routine
|
|||
|
and supplies the wrong arguments.
|
|||
|
The kernel can optionally protect against this by making rigorous version
|
|||
|
checks on the module as it is loaded.
|
|||
|
|
|||
|
<p>
|
|||
|
|
|||
|
<H2><A NAME="tth_sEc12.1">12.1 </A> Loading a Module</H2>
|
|||
|
|
|||
|
<p>
|
|||
|
|
|||
|
<p><A NAME="tth_fIg12.1"></A>
|
|||
|
<center><center> <img src="modules.gif"><br>
|
|||
|
<p>
|
|||
|
</center></center><center> Figure 12.1: The List of Kernel Modules</center>
|
|||
|
<A NAME="modules-figure"></A>
|
|||
|
<p>
|
|||
|
<p>There are two ways that a kernel module can be loaded.
|
|||
|
The first way is to use the <font face="helvetica">insmod</font> command to manually insert the it into
|
|||
|
the kernel.
|
|||
|
|
|||
|
<p>
|
|||
|
The second, and much more clever way, is to load the module as it is needed; this
|
|||
|
is known as demand loading.
|
|||
|
|
|||
|
<p>
|
|||
|
When the kernel discovers the need for a module, for example when the user mounts
|
|||
|
a file system that is not in the kernel, the kernel will request that the kernel daemon
|
|||
|
(<tt>kerneld</tt>) attempts to load the appropriate module.
|
|||
|
|
|||
|
<p>
|
|||
|
The kernel daemon is a normal user process albeit with super user privileges.
|
|||
|
When it is started up, usually at system boot time, it opens up an Inter-Process
|
|||
|
Communication (IPC) channel to the kernel.
|
|||
|
This link is used by the kernel to send messages to the <tt>kerneld</tt> asking for
|
|||
|
various tasks to be performed.
|
|||
|
|
|||
|
<p>
|
|||
|
<tt>Kerneld</tt>'s major function is to load and unload kernel modules but it is also
|
|||
|
capable of other tasks such as starting up the PPP link over serial line when it
|
|||
|
is needed and closing it down when it is not.
|
|||
|
<tt>Kerneld</tt> does not perform these tasks itself, it runs the neccessary programs
|
|||
|
such as <font face="helvetica">insmod</font> to do the work.
|
|||
|
<tt>Kerneld</tt> is just an agent of the kernel, scheduling work on its behalf.
|
|||
|
|
|||
|
<p>
|
|||
|
The <font face="helvetica">insmod</font> utility must find the requested kernel module that it is to load.
|
|||
|
Demand loaded kernel modules are normally kept in <tt>/lib/modules/kernel-version</tt>.
|
|||
|
The kernel modules are linked object files just like other programs in the system
|
|||
|
except that they are linked as a relocatable images.
|
|||
|
That is, images that are not linked to run from a particular address.
|
|||
|
They can be either <tt>a.out</tt> or <tt>elf</tt> format object files.
|
|||
|
<font face="helvetica">insmod</font> makes a privileged system call to find the kernel's exported symbols.
|
|||
|
|
|||
|
<p>
|
|||
|
These are kept in pairs containing the symbol's name and its value, for example its
|
|||
|
address.
|
|||
|
The kernel's exported symbol table is held in the first <tt>module</tt> data structure
|
|||
|
in the list of modules maintained by the kernel and pointed at by the <tt>module_list</tt>
|
|||
|
pointer.
|
|||
|
|
|||
|
<p>
|
|||
|
Only specifically entered symbols are added into the table, which is built when the
|
|||
|
kernel is compiled and linked, not <em>every</em> symbol in the kernel is exported to
|
|||
|
its modules.
|
|||
|
An example symbol is <tt>``request_irq''</tt> which is the kernel routine that must
|
|||
|
be called when a driver wishes to take control of a particular system interrupt.
|
|||
|
In my current kernel, this has a value of <em>0x0010cd30</em>.
|
|||
|
You can easily see the exported kernel symbols and their values by looking at
|
|||
|
<tt>/proc/ksyms</tt> or by using the <font face="helvetica">ksyms</font> utility.
|
|||
|
The <font face="helvetica">ksyms</font> utility can either show you all of the exported kernel symbols or only
|
|||
|
those symbols exported by loaded modules.
|
|||
|
<font face="helvetica">insmod</font> reads the module into its virtual memory and fixes up its unresolved
|
|||
|
references to kernel routines and resources using the exported symbols from the
|
|||
|
kernel.
|
|||
|
This fixing up takes the form of patching the module image in memory.
|
|||
|
<font face="helvetica">insmod</font> physically writes the address of the symbol into the appropriate
|
|||
|
place in the module.
|
|||
|
|
|||
|
<p>
|
|||
|
When <font face="helvetica">insmod</font> has fixed up the module's references to exported kernel symbols,
|
|||
|
it asks the kernel for enough space to hold the new kernel, again using a
|
|||
|
privileged system call.
|
|||
|
The kernel allocates a new <tt>module</tt> data structure and enough kernel
|
|||
|
memory to hold the new module and puts it at the end of the kernel modules list.
|
|||
|
The new module is marked as <tt>UNINITIALIZED</tt>.
|
|||
|
|
|||
|
<p>
|
|||
|
Figure <A href="#modules-figure"
|
|||
|
> 12.1</A> shows the list of kernel modules after two modules,
|
|||
|
<tt>VFAT</tt> and <tt>VFAT</tt> have been loaded into the kernel.
|
|||
|
Not shown in the diagram is the first module on the list, which is a pseudo-module that is only
|
|||
|
there to hold the kernel's exported symbol table.
|
|||
|
You can use the command <font face="helvetica">lsmod</font> to list all of the loaded kernel modules and
|
|||
|
their interdependencies.
|
|||
|
<font face="helvetica">lsmod</font> simply reformats <tt>/proc/modules</tt> which is built from the list of kernel
|
|||
|
<tt>module</tt> data structures.
|
|||
|
The memory that the kernel allocates for it is mapped into the <font face="helvetica">insmod</font> process's
|
|||
|
address space so that it can access it.
|
|||
|
<font face="helvetica">insmod</font> copies the module into the allocated space and relocates it so
|
|||
|
that it will run from the kernel address that it has been allocated.
|
|||
|
This must happen as the module cannot expect to be loaded at the same address
|
|||
|
twice let alone into the same address in two different Linux systems.
|
|||
|
Again, this relocation involves patching the module image with the appropriate
|
|||
|
addresses.
|
|||
|
|
|||
|
<p>
|
|||
|
The new module also exports symbols to the kernel and <font face="helvetica">insmod</font> builds a table
|
|||
|
of these exported images.
|
|||
|
Every kernel module must contain module initialization and module cleanup
|
|||
|
routines and these symbols are deliberately not exported but <font face="helvetica">insmod</font> must
|
|||
|
know the addresses of them so that it can pass them to the kernel.
|
|||
|
All being well, <font face="helvetica">insmod</font> is now ready to initialize the module and it makes
|
|||
|
a privileged system call passing the kernel the addresses of the module's initialization
|
|||
|
and cleanup routines.
|
|||
|
|
|||
|
<p>
|
|||
|
When a new module is added into the kernel, it must update the kernel's set of symbols
|
|||
|
and modify the modules that are being used by the new module.
|
|||
|
Modules that have other modules dependent on them must maintain a list of references
|
|||
|
at the end of their symbol table and pointed at by their <tt>module</tt> data structure.
|
|||
|
Figure <A href="#modules-figure"
|
|||
|
> 12.1</A> shows that the <tt>VFAT</tt> file system module is dependent on the
|
|||
|
<tt>FAT</tt> file system module.
|
|||
|
So, the <tt>FAT</tt> module contains a reference to the <tt>VFAT</tt> module; the reference
|
|||
|
was added when the <tt>VFAT</tt> module was loaded.
|
|||
|
The kernel calls the modules initialization routine and, if it is successful it
|
|||
|
carries on installing the module.
|
|||
|
The module's cleanup routine address is stored in it's <tt>module</tt> data structure and
|
|||
|
it will be called by the kernel when that module is unloaded.
|
|||
|
Finally, the module's state is set to <tt>RUNNING</tt>.
|
|||
|
|
|||
|
<p>
|
|||
|
|
|||
|
<H2><A NAME="tth_sEc12.2">12.2 </A> Unloading a Module</H2>
|
|||
|
|
|||
|
<p>
|
|||
|
Modules can be removed using the <font face="helvetica">rmmod</font> command but demand loaded modules
|
|||
|
are automatically removed from the system by <tt>kerneld</tt> when they are no longer being used.
|
|||
|
Every time its idle timer expires, <tt>kerneld</tt> makes a system call requesting that
|
|||
|
all unused demand loaded modules are removed from the system.
|
|||
|
The timer's value is set when you start <tt>kerneld</tt>; my <tt>kerneld</tt> checks every
|
|||
|
180 seconds.
|
|||
|
So, for example, if you mount an <tt>iso9660</tt> CD ROM and your <tt>iso9660</tt> filesystem
|
|||
|
is a loadable module, then shortly after the CD ROM is unmounted, the <tt>iso9660</tt>
|
|||
|
module will be removed from the kernel.
|
|||
|
|
|||
|
<p>
|
|||
|
A module cannot be unloaded so long as other components of the kernel are depending
|
|||
|
on it.
|
|||
|
For example, you cannot unload the <tt>VFAT</tt> module if you have one or
|
|||
|
more <tt>VFAT</tt> file systems mounted.
|
|||
|
If you look at the output of <font face="helvetica">lsmod</font>, you will see that each module has
|
|||
|
a count associated with it.
|
|||
|
For example:
|
|||
|
|
|||
|
<pre>
|
|||
|
Module: #pages: Used by:
|
|||
|
msdos 5 1
|
|||
|
vfat 4 1 (autoclean)
|
|||
|
fat 6 [vfat msdos] 2 (autoclean)
|
|||
|
</pre>
|
|||
|
<p>
|
|||
|
The count is the number of kernel entities that are dependent on this module.
|
|||
|
In the above example, the <tt>vfat</tt> and <tt>msdos</tt> modules are both dependent on
|
|||
|
the <tt>fat</tt> module and so it has a count of 2.
|
|||
|
Both the <tt>vfat</tt> and <tt>msdos</tt> modules have 1 dependent, which is a mounted
|
|||
|
file system.
|
|||
|
If I were to load another <tt>VFAT</tt> file system then the <tt>vfat</tt> module's
|
|||
|
count would become 2.
|
|||
|
A module's count is held in the first longword of its image.
|
|||
|
|
|||
|
<p>
|
|||
|
This field is slightly overloaded as it also holds the <tt>AUTOCLEAN</tt> and <tt>VISITED</tt>
|
|||
|
flags.
|
|||
|
Both of these flags are used for demand loaded modules.
|
|||
|
These modules are marked as <tt>AUTOCLEAN</tt> so that the system can recognize
|
|||
|
which ones it may automatically unload.
|
|||
|
The <tt>VISITED</tt> flag marks the
|
|||
|
module as in use by one or more other system components; it is set whenever another
|
|||
|
component makes use of the module.
|
|||
|
Each time the system is asked by <tt>kerneld</tt> to remove unused demand loaded modules
|
|||
|
it looks through all of the modules in the system for likely candidates.
|
|||
|
It only looks at modules marked as <tt>AUTOCLEAN</tt> and in the state <tt>RUNNING</tt>.
|
|||
|
If the candidate has its <tt>VISITED</tt> flag cleared then it will remove the
|
|||
|
module, otherwise it will clear the <tt>VISITED</tt> flag and go on to look at the next
|
|||
|
module in the system.
|
|||
|
|
|||
|
<p>
|
|||
|
Assuming that a module can be unloaded, its cleanup routine is called to allow
|
|||
|
it to free up the kernel resources that it has allocated.
|
|||
|
|
|||
|
<p>
|
|||
|
The <tt>module</tt> data structure is marked as <tt>DELETED</tt> and it is unlinked
|
|||
|
from the list of kernel modules.
|
|||
|
Any other modules that it is dependent on have their reference lists modified
|
|||
|
so that they no longer have it as a dependent.
|
|||
|
All of the kernel memory that the module needed is deallocated.
|
|||
|
|
|||
|
<p>
|
|||
|
|
|||
|
<p><hr><small>File translated from T<sub><font size=-1>E</font></sub>X by <a href="http://hutchinson.belmont.ma.us/tth/tth.html">T<sub><font size=-1>T</font></sub>H</a>, version 1.0.</small>
|
|||
|
<hr>
|
|||
|
<center>
|
|||
|
<A HREF="../modules/modules.html"> Top of Chapter</A>,
|
|||
|
<A HREF="../tlk-toc.html"> Table of Contents</A>,
|
|||
|
<A href="../tlk.html" target="_top"> Show Frames</A>,
|
|||
|
<A href="../modules/modules.html" target="_top"> No Frames</A><br>
|
|||
|
<EFBFBD> 1996-1999 David A Rusling <A HREF="../misc/copyright.html">copyright notice</a>.
|
|||
|
</center>
|
|||
|
</HTML>
|