Supporting multiple module initialization functions
[Posted June 24, 2003 by corbet]
One longstanding goal in kernel development has been to eliminate the
differences between loadable modules and monolithic (linked-in) code. The
fewer differences there are, the easier it is to write code which works in
either mode - and to maintain that code. In 2.5, this process is almost
complete; there is very little code which is unique to either modules or
monolithic code.
One remaining difference, however, has to do with initialization and exit
code. It is possible to use the module_init() macro to designate an
initialization function, and that function will be called properly at
module load time or at boot
time if the module is built directly into the kernel. (Exit
functions for monolithic code are, of course, simply discarded.) One
important difference remains, however: monolithic code can have multiple
initialization calls, while modules can only have one. Monolithic
code initialization calls can even be given priorities (via macros like
core_initcall() or late_initcall()) which control when
each function is called.
One would think this wouldn't matter a whole lot for loadable modules,
since every initialization function would be called at the same time
(when the module is loaded) anyway. But this difference forces module and
monolithic code to be different. It also prevents the creation of nice,
initialization-time macros which ease the process of setting up
/proc files or sysfs entries.
With a new patch (since revised) from Rusty Russell, things
will change. Rusty notes the real reason why modules can only have a
single set of initialization and exit functions: the kernel simply does not
know what to do if one of a series of initialization functions fails. In
that case, the module load process must fail, and some sort of cleanup must
be performed. The problem is knowing what that cleanup is.
The solution is to associate pairs of initialization and exit functions.
That is done with a new macro:
module_init_exit(priority, init_fn, exit_fn);
This call designates a new initialization and exit function pair, and
associates a priority with that pair.
Each exit function cleans up (only) the work done by its associated
initialization function. At module load time, the initialization functions
are called in increasing priority order. Should one fail, the exit
functions corresponding to the initialization functions that succeeded will
be called, in reverse priority order. Thus, a properly-written module
should be able to clean up after itself correctly after a failure in any
part of the initialization process.
An early version of this patch broke modules using the long-deprecated
technique of calling their initialization and exit functions
init_module() and cleanup_module(), respectively. That
has since been patched up - this stage of the kernel development process is
not the time to be making such changes. But the writing is on the wall,
and that particular technique is not likely to survive past 2.7.
(
Log in to post comments)