LWN.net Logo

 


 
Summary page
Return to the Kernel page
 
Recent Features

LWN.net Weekly Edition for March 18, 2004

LWN.net Weekly Edition for March 11, 2004

The annotated SCO stock price chart

A grumpy editor's calendar search

LWN.net Weekly Edition for March 4, 2004

Printable page
 

 

Driver porting: more module changes

This article is part of the LWN Porting Drivers to 2.6 series.
The first article in this series noted a couple of changes that result from the new, kernel-based module loader. In particular, explicit module_init() and module_exit() declarations are now necessary. Quite a few other things have changed as well, however; this article will summarize the most important of those changes.

Module parameters

The old MODULE_PARM macro, which used to specify parameters which can be passed to the module at load time, is no more. The new parameter declaration scheme add type safety and new functionality, but at the cost of breaking compatibility with older modules.

Modules with parameters should now include <linux/moduleparam.h> explicitly. Parameters are then declared with module_param:

    module_param(name, type, perm);
Where name is the name of the parameter (and of the variable holding its value), type is its type, and perm is the permissions to be applied to that parameter's sysfs entry. The type parameter can be one of byte, short, ushort, int, uint, long, ulong, charp, bool or invbool. That type will be verified during compilation, so it is no longer possible to create confusion by declaring module parameters with mismatched types. The plan is for module parameters to appear automatically in sysfs, but that feature had not been implemented as of 2.6.0-test9; for now, the safest alternative is to set perm to zero, which means "no sysfs entry."

If the name of the parameter as seen outside the module differs from the name of the variable used to hold the parameter's value, a variant on module param may be used:

    module_param_named(name, value, type, perm);
Where name is the externally-visible name and value is the internal variable.

String parameters will normally be declared with the charp type; the associated variable is a char pointer which will be set to the parameter's value. If you need to have a string value copied directly into a char array, declare it as:

    module_param_string(name, string, len, perm);
Usually, len is best specified as sizeof(string).

Finally, array parameters (supplied at module load time as a comma-separated list) may be declared with:

    module_param_array(name, type, num, perm);

The one parameter not found in module_param() (num) is an output parameter; if a value for name is supplied when the module is loaded, num will be set to the number of values given. This macro uses the declared length of the array to ensure that it is not overrun if too many values are provided.

As an example of how the new module parameter code works, here is a paramaterized version of the "hello world" module shown previously:

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/moduleparam.h>
    
    MODULE_LICENSE("Dual BSD/GPL");
    
    /*
     * A couple of parameters that can be passed in: how many times we say
     * hello, and to whom.
     */
    static char *whom = "world";
    module_param(whom, charp, 0);
    static int howmany = 1;
    module_param(howmany, int, 0);
    
    
    static int hello_init(void)
    {
        int i;
        for (i = 0; i < howmany; i++)
	    printk(KERN_ALERT "(%d) Hello, %s\n", i, whom);
        return 0;
    }
    
    static void hello_exit(void)
    {
    	printk(KERN_ALERT "Goodbye, cruel %s\n", whom);
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
Inserting this module with a command like:
    insmod ./hellop.ko howmany=2 whom=universe
causes the message "hello, universe" to show up twice in the system logfile.

Module aliases

A module alias is an alternative name by which a loadable module can be known. These aliases are typically defined in /etc/modules.conf, but many of them are really a feature of the module itself. In 2.6, module aliases can be embedded with a module's source. Simply add a line like:

    MODULE_ALIAS("alias-name");

The module use count

In 2.4 and prior kernels, modules maintained their "use count" with macros like MOD_INC_USE_COUNT. The use count, of course, is intended to prevent modules from being unloaded while they are being used. This method was always somewhat error prone, especially when the use count was manipulated inside the module itself. In the 2.6 kernel, reference counting is handled differently.

The only safe way to manipulate the count of references to a module is outside of the module's code. Otherwise, there will always be times when the kernel is executing within the module, but the reference count is zero. So this work has been moved outside of the modules, and life is generally easier for module authors.

Any code which wishes to call into a module (or use some other module resource) must first attempt to increment that module's reference count:

    int try_module_get(&module);
It is also necessary to look at the return value from try_module_get(); a zero return means that the try failed, and the module should not be used. Failure can happen, for example, when the module is in the process of being unloaded.

A reference to a module can be released with module_put().

Again, modules will not normally have to manage their own reference counts. The only exception may be if a module provides a reference to an internal data structure or function that is not accounted for otherwise. In that (rare) case, a module could conceivably call try_module_get() on itself.

As of this writing, modules are considered "live" during initialization, meaning that a try_module_get() will succeed at that time. There is still talk of changing things, however, so that modules are not accessible until they have completed their initialization process. That change will help prevent a whole set of race conditions that come about when a module fails initialization, but it also creates difficulties for modules which have to be available early on. For example, block drivers should be available to read partition tables off of disks when those disks are registered, which usually happens when the module is initializing itself. If the policy changes and modules go back off-limits during initialization, a call to a function like make_module_live() may be required for those modules which must be available sooner. (Update 2.6.0-test9: this change has not happened and seems highly unlikely at this point).

Finally, it is not entirely uncommon for driver authors to put in a special ioctl() function which sets the module use count to zero. Sometimes, during module development, errors can leave the module reference count in a state where it will never reach zero, and there was no other way to get the kernel to unload the module. The new module code supports forced unloading of modules which appear to have outstanding references - if the CONFIG_MODULE_FORCE_UNLOAD option has been set. Needless to say, this option should only be used on development systems, and, even then, with great caution.

Exporting symbols

For the most part, the exporting of symbols to the rest of the kernel has not changed in 2.6 - except, of course, for the fact that any user of those symbols should be using try_module_get() first. In older kernels, however, a module which did not arrange things otherwise would implicitly export all of its symbols. In 2.6, things no longer work that way; only symbols which have explicitly been exported are visible to the rest of the kernel.

Chances are that change will cause few problems. When you get a chance, however, you can remove EXPORT_NO_SYMBOLS lines from your module source. Exporting no symbols is now the default, so EXPORT_NO_SYMBOLS is a no-op.

The 2.4 inter_module_ functions have been deprecated as unsafe. The symbol_get() function exists for the cases when normal symbol linking does not work well enough. Its use requires setting up weak references at compile time, and is beyond the scope of this document; there are no users of symbol_get() in the 2.6.0-test9 kernel source.

Kernel version checking

2.4 and prior kernels would include, in each module, a string containing the version of the kernel that the module was compiled against. Normally, modules would not be loaded if the compile version failed to match the running kernel.

In 2.5, things still work mostly that way. The kernel version is loaded into a separate, "link-once" ELF section, however, rather than being a visible variable within the module itself. As a result, multi-file modules no longer need to define __NO_VERSION__ before including <linux/module.h>.

The new "version magic" scheme also records other information, including the compiler version, SMP status, and preempt status; it is thus able to catch more incompatible situations than the old scheme did.

Module symbol versioning ("modversions") has been completely reworked for the 2.6 kernel. Module authors who use the makefiles shipped with the kernel (and that is about the only way to work now) will find that dealing with modversions has gotten easier than before. The #define hack which tacked checksums onto kernel symbols has gone away in favor of a scheme which stores checksum information in a separate ELF section.


Post a comment

  Driver porting: more module changes
(Posted Feb 14, 2003 8:41 UTC (Fri) by rusty) (Post reply)

Regarding module_param(): MODULE_PARM() will certainly stay throughout the 2.6 series, so no need to change existing code just yet.

However, the real power of module_param() is that you can easily build your own types: i.e. it is extensible. One way to do this is to use the underlying module_param_call() macro, but a more convenient way goes like this:

 #define param_check_mytype(name, p) /* optional typechecking */
 int param_set_mytype(const char *val, struct kernel_param *kp) ...
 int param_get_mytype(char *buffer, struct kernel_param *kp) ...
Then you can use it as follows:
 module_param(myparam, mytype, 000);
This is extremely useful for implementing things like ranges, or any holes in the provided macros.

The other issue to note is that (as an unrelated bonus) the module_param parameters are also available as boot parameters, prefixed with the module name and a "." (- and _ can be used interchangably here). Previously __setup() was needed for boot parameters, and MODULE_PARM for module parameters.

Hope that helps!
Rusty.

  Driver porting to 2.5.59: 'MOD_IN_USE' undeclared
(Posted Feb 27, 2003 8:12 UTC (Thu) by hsieng) (Post reply)

Hello,

While compiling a device driver in 2.5.59, I get the following error:

dmodule.c: 'MOD_IN_USE' undeclared

Please help on how to solve this problem.

Thank you.

Se-Hsieng


  Driver porting: more module changes
(Posted Feb 21, 2003 6:35 UTC (Fri) by mmarq) (Post reply)

Well, I wonder why bother, ...perahps going for one of the kernel maintainers listed emails,...but then, if anyone can answer to this question i'l be very much appreciataded...it's very important to me!!!

Does this >"new "version magic" scheme also records other information, including the compiler version, SMP status, and preempt status; it is thus able to catch more incompatible situations than the old scheme did"<, storm, is to be lefted in production 2.6 kernels, or is it going to be somehow abstracted??

Better put!, does a "stupid trying to be a hacker" programmer like me, if by any change achieves the feat of getting a working kernel hardware driver module for the most trivial piece of hardware in the world, say, compiled with kernel 2.6.6 and gcc 3.4, "be in a versioning storm" and have to fix the module for it to recompile with preempt enable, and fix the module againg for it to recompile with SMP enabled, and for Kernel 2.6.7 the same, and for gcc3.4.1 the same,..., meaning that 20 kernel versions and 3 compiler versions ahead i would have to make 180 fixes!?????

whaw!!...without meaning any disrespect, it sure is a job for a full time payed hacker!

Well!!...If the answer is yes than is very sad "for me and for thousands like me,...because i have a very small shop that transforms old gear and also produce new linux servers and firewall appliences, and dont have the many to hire an army of programmers.

Its double sad, because after 10 years of dreams and foughts, the kernel is sleeping to the hands of IBM, HP and the like, that not only have the resources for thousands of programmers, but also control the machines on witch full working kernels can be deployed.

Any way, i respectfuly be waiting for a answer.... thank you.

  Driver porting: more module changes
(Posted Feb 21, 2003 10:17 UTC (Fri) by rrw) (Post reply)

I think that there is one problem with this scheme of parameters. In case of numbers you cannot distinguish if the user didn't set the parameter or if he has set it to zero. Perheaps example will explain it better:

module_param(howmany, int, 0);

if you load this module with howmany=0, howmany will be zero. But if you omit howmany on modload commandline, howmany will be also zero.

One should pass the numeric arguments to the code as (int *), not the (int). Then NULL will be ``not set''.

Copyright (©) 2003, Eklektix, Inc.
Linux (®) is a registered trademark of Linus Torvalds
Powered by Rackspace Managed Hosting.