Sie sind auf Seite 1von 40

The Kernel Symbol Table

insmod resolves undefined symbols against


the table of public kernel symbols.

The Kernel Symbol Table

insmod resolves undefined symbols against


the table of public kernel symbols.

This table contains the addresses of global


kernel items functions and variables that are
needed to implement modularized drivers.

The Kernel Symbol Table

insmod resolves undefined symbols against


the table of public kernel symbols.

This table contains the addresses of global


kernel items functions and variables that are
needed to implement modularized drivers.

The public symbol table can be read in text


form from the file /proc/kallsyms.

The Kernel Symbol Table

insmod resolves undefined symbols against


the table of public kernel symbols.

This table contains the addresses of global


kernel items functions and variables that are
needed to implement modularized drivers.

The public symbol table can be read in text


form from the file /proc/kallsyms.

When a module is loaded, any symbol


exported by the module becomes part of the
kernel symbol table, and you can see it
appear in /proc/ksyms or in the output of
theksyms command

Ne modules can use symbols exported by your


module, and you can stack ne modules on top of
other modules.

Ne modules can use symbols exported by your


module, and you can stack ne modules on top of
other modules.

!inux allos module stacking, this is here one


module re"uires the services of another module.

modprobe functions in much the same ay as


insmod, but it also loads any other modules that are
re"uired by the module you ant to load. Thus, one
modprobe command can sometimes replace several
invocations of insmod.

#f your module exports no symbols at all, you might


ant to make that explicit by placing a line ith this
macro call in your source file$
EXPORT_NO_SYMBOLS;

The macro expands to an assembler directive and


may appear anyhere ithin the module. %ortable
code, hoever, should place it ithin the module
initialization function &init'module(, because the
version of this macro defined in sysdep.h for older
kernels ill ork only there.

#f, on the other hand, you need to export a subset of


symbols from your module, the first step is defining
the preprocessor macro )*%+,T'S-.T/0. This
macro must be defined before including module.h.

#f, on the other hand, you need to export a subset of


symbols from your module, the first step is defining
the preprocessor macro )*%+,T'S-.T/0. This
macro must be defined before including module.h.

#f )*%+,T'S-.T/0 is defined, individual symbols


are exported ith a couple of macros$
EXPORT_SYMBOL (name);
EXPORT_SYMBOL_NOVERS (name);

)xample $

1ile 2module3.c4
!e"#ne EXPORT_SYMT$B
#ncl%!e&l#n%'/mo!%le()*
#ncl%!e&l#n%'/kernel()*
#ncl%!e&l#n%'/#n#+()*
#n+ ,al-./;
EXPORT_SYMBOL(,al);
s+a+#c #n+ my_#n#+(,o#!)
0
pr#n+k(1&.*2n#+#al#3a+#on o" mo!%le. ,al-
4!5n16,al);
re+%rn /;
7
s+a+#c ,o#! my_e'#+(,o#!)
0
pr#n+k(1&.* Term#na+#on o" mo!%le.(((5n1);
7
mo!%le_#n#+(my_#n#+);
mo!%le_e'#+(my_e'#+);

module5.c
#ncl%!e&l#n%'/mo!%le()*
#ncl%!e&l#n%'/kernel()*
#ncl%!e&l#n%'/#n#+()*
e'+ern #n+ ,al;
s+a+#c #n+ my_#n#+(,o#!)
0
pr#n+k(1&.*2n#+#al#3a+#on o" mo!%le8 ,al-
4!5n16,al);
re+%rn /;
7
s+a+#c ,o#! my_e'#+(,o#!)
0
pr#n+k(1&.* Term#na+#on o" mo!%le8(((5n1);
7
mo!%le_#n#+(my_#n#+);
mo!%le_e'#+(my_e'#+);

.ake file$

!oad modules...

No -ou can see kernel messages


ob67m $8 module3.o
ob67m $8 module5.o
9insmod module3.ko
9insmod module5.ko
9 dmesg
#nitialization of module3 val83:
#nitialization of module5 val83:

#nitialization and ;leanup 1unctions

The initialization function registers any facility offered


by the module.

#nitialization and ;leanup 1unctions

The initialization function registers any facility offered


by the module.

0y facility, e mean a ne functionality, be it a hole


driver or a ne softare abstraction, that can be
accessed by an application

#nitialization and ;leanup 1unctions

The initialization function registers any facility offered


by the module.

0y facility, e mean a ne functionality, be it a hole


driver or a ne softare abstraction, that can be
accessed by an application

.odules can register many different types of


facilities< for each facility, there is a specific kernel
function that accomplishes this registration.

#nitialization and ;leanup 1unctions

The initialization function registers any facility offered


by the module.

0y facility, e mean a ne functionality, be it a hole


driver or a ne softare abstraction, that can be
accessed by an application

.odules can register many different types of


facilities< for each facility, there is a specific kernel
function that accomplishes this registration.

The arguments passed to the kernel registration


functions are usually a pointer to a data structure
describing the ne facility and the name of the facility
being registered.

)rror =andling in init'module

#f any errors occur hen you register utilities, you


must undo any registration activities performed
before the failure.

#f any errors occur hen you register utilities, you


must undo any registration activities performed
before the failure.

/n error can happen, for example, if there isn>t


enough memory in the system to allocate a ne data
structure or because a resource being re"uested is
already being used by other drivers.

good program code must be prepared to handle this


event.
)rror =andling in init'module

!inux doesn>t keep a permodule registry of facilities


that have been registered, so the module must back
out of everything itself if init'module fails at some
point
)rror =andling in init'module

!inux doesn>t keep a permodule registry of facilities


that have been registered, so the module must back
out of everything itself if init'module fails at some
point

#f you ever fail to unregister hat you obtained,


thekernel is left in an unstable state$ you can>t
register your facilities again by reloading the module
because they ill appear to be busy, and you can>t
unregister them because you>d need the same
pointer you used to register and you>re not likely to
be able to figure out the address
)rror =andling in init'module

)rror recovery is sometimes best handled ith the


goto statement.

The folloing sample code &using fictitious


registration and unregistration functions( behaves
correctly if initialization fails at any point.
)rror =andling in init'module

This code attempts to register three &fictitious(


facilities. The goto statement is used in case of
failure to cause the unregistration of only the facilities
that had been successfully registered before things
ent bad.
)rror =andling in init'module

/nother option, is keeping track of hat has been


successfully registered and calling cleanup'module
in case of any error.

The cleanup function ill only unroll the steps that


have been successfully accomplished.

This alternative, hoever, re"uires more code and


more ;%? time, so in fast paths you>ll still resort to
goto as the best errorrecovery tool.

The return value of init'module, err, is an error code.


)rror =andling in init'module

cleanup'module must undo any registration


performed by init'module, and it is customary &but
not mandatory( to unregister facilities in the reverse
order used to register them$
)rror =andling in init'module

#f your initialization and cleanup are more complex


than dealing ith a fe items, the goto approach may
become difficult to manage, because all the cleanup
code must be repeated ithin init'module, ith
several labels intermixed. Sometimes, therefore, a
different layout of the code proves more successful.

What you>d do to minimize code duplication and keep


everything streamlined is to call cleanup'module
from ithin init'module henever an error occurs.
The cleanup function, then, must check the status of
each item before undoing its registration. #n its
simplest form, the code looks like the
)rror =andling in init'module

)rror =andling in init'module

)rror =andling in init'module

The ?sage ;ount

The system keeps a usage count for every module


in order to determine hether the module can be
safely removed.

The ?sage ;ount

The system keeps a usage count for every module


in order to determine hether the module can be
safely removed.

The system needs this information because a


module can>t be unloaded if it is busy$ you can>t
remove a filesystem type hile the filesystem is
mounted, and you can>t drop a char device hile a
process is using it, or you>ll experience some sort of
segmentation fault or kernel panic hen ild
pointers get dereferenced.

#n modern kernels, the system can automatically


track the usage count for you.

#n older versions of the kernel, you ill need to ad6ust


the usage count manually.
The ?sage ;ount

#n modern kernels, the system can automatically


track the usage count for you.

#n older versions of the kernel, you ill need to ad6ust


the usage count manually.

To ork ith the usage count, use these three


macros$
MO9_2N:_;SE_:O;NT $ #ncrements the count for the
current module
MO9_9E:_;SE_:O;NT $ @ecrements the count.
MO9_2N_;SE $ )valuates to true if the count is not zero.
The ?sage ;ount

The macros are defined in AlinuxBmodule.hC, and


they act on internal data structures that shouldn>t be
accessed directly by the programmer.

There>s no need to check for MO9_2N_;SE from


ithin cleanup'module, because the check is
performed by the system call
sys_!ele+e_mo!%le&defined in kernelBmodule.c( in
advance.

%roper management of the module usage count is


critical for system stability
The ?sage ;ount

The current value of the usage count is found in the


third field of each entry in /proc/modules. This file
shos the modules currently loaded in the system,
ith one entry for each module. The fields are the
name of the module, the number of bytes of memory
it uses, and the current
This is a typical BprocBmodules file$
parport_pc 7604 1 (autoclean)
lp 4800 0 (unused)
parport 8084 1 [parport_probe parport_pc lp]
lockd 33256 1 (autoclean)
sunrpc 56612 1 (autoclean) [lockd]
The ?sage ;ount

?nloading

To unload a module, use the rmmod command. #ts


task is much simpler than loading, since no linking
has to be performed.

The command invokes the sys_!ele+e_mo!%le


system call, hich calls clean%p_mo!%le in the
module itself if the usage count is zero or returns an
error otherise.

The clean%p_mo!%le implementation is in charge of


unregistering every item that as registered by the
module. +nly the exported symbols are removed
automatically.

)xplicit #nitialization and ;leanup
1unctions

/s e have seen, the kernel calls initialization


function to initialize a nely loaded module, and calls
cleanup function 6ust before module removal.

#n modern kernels, hoever, these functions often


have different names.

/s of kernel 5.D.3D, a facility exists for explicitly


naming the module initialization and cleanup
routines< using this facility is the preferred
programming style.

;onsider an example. #f your module names its


initialization routine my'init &instead of init'module( and
its cleanup routine my'cleanup, you ould mark them
ith the folloing to lines &usually at the end of the
source file($
module'init&my'init(<
module'exit&my'cleanup(<

Note that your code must include AlinuxBinit.hC to use


module'init and module'exit.
)xplicit #nitialization and ;leanup
1unctions

The advantage of doing things this ay is that each


initialization and cleanup function in the kernel can
have a uni"ue name, hich helps ith debugging.

These functions also make life easier for those


riting drivers that ork either as a module or built
directly into the kernel.

=oever, use of module'init and module'exit is not


re"uired if your initialization and cleanup functions
use the old names. #n fact, for modules, the only
thing they do is define init'module and
cleanup'module as ne names for the given
functions.
)xplicit #nitialization and ;leanup
1unctions

#f you dig through the kernel source &in versions 5.5


and later(, you ill likely see a slightly different form
of declaration for module initialization and cleanup
functions, hich looks like the folloing$
static int ' 'init my'init&void(
E
....
F
static void ' 'exit my'cleanup&void(
E
....
F
)xplicit #nitialization and ;leanup
1unctions

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
static int __init hello_2_init(void)
{
printk(KE!_"!#$ %&ello' (orld 2)n%)*
return +*
,
static void __exit hello_2_exit(void)
{
printk(KE!_"!#$ %-ood./e' (orld 2)n%)*
,
module_init(hello_2_init)*
module_exit(hello_2_exit)*

The attribute ''init, hen used in this ay, ill cause


the initialization function to be discarded, and its
memory reclaimed, after initialization is complete. #t
only orks, hoever, for builtin drivers< it has no
effect on modules.

' 'exit, instead, causes the omission of the marked


function hen the driver is not built as a module<
again, in modules, it has no effect.

The use of ' 'init can reduce the amount of memory


used by the kernel
)xplicit #nitialization and ;leanup
1unctions

Das könnte Ihnen auch gefallen