http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:modules:example
This example shows how to create and build a module outside of the kernel tree, and install and remove it.
While it is always best to keep the module as part of the kernel source tree (in the same source directory), so it can pick up the correct header files properly, it is not necessary. This example assumes that the kernel is installed at /home/uClinux-dist
and the example module files are created in the /home/module-example
directory. If your installation is in different paths, you will need to change the command line build options.
The first file which must be created is the module itself.
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> #include <linux/platform_device.h> MODULE_DESCRIPTION("sample module"); MODULE_LICENSE("GPL"); static int sample_module_drv_probe(struct device *dev) { printk(KERN_DEBUG "probe sample module device\n"); return 0; } static int sample_module_drv_remove(struct device *dev) { printk(KERN_DEBUG "remove sample module device\n"); return 0; } static struct device_driver sample_module_driver = { .name = "sample_module", .bus = &platform_bus_type, .probe = sample_module_drv_probe, .remove = sample_module_drv_remove, }; static int __init sample_module_init(void) { printk(KERN_DEBUG "init sample module device\n"); return driver_register(&sample_module_driver); } static void __exit sample_module_cleanup(void) { printk(KERN_DEBUG "cleanup sample module device\n"); driver_unregister(&sample_module_driver); } module_init(sample_module_init); module_exit(sample_module_cleanup);
The 2nd file which must be created is the Makefile for the module.
obj-m := sample_module.o
If there were multiple c files (file1.c
and file2.c
) which needed to be linked for the module to build properly, the Makefile
would look something like:
obj-m := sample_module.o sample_module-objs := file1.o file2.o
Since the kernel and module share resources, the kernel must be set up properly to install and remove modules.
Make sure the following settings are enabled:
Linux Kernel Configuration Loadable module support [*] Enable loadable module support [*] Module unloading Application Main Menu BusyBox [*] insmod [*] insmod: lsmod [*] insmod: modprobe [*] insmod: rmmod [*] insmod: 2.6 and above kernel modules [*] insmod: Model version checks [*] insmod: load in kernel memory
and then what ever other kernel/application options you may want to set for your build and platform. When building a kernel with loadable module support, but no loadable modules, you may get warnings like:
BFD: /home/uClinux-dist/images/linux: warning: Empty loadable segment detected, is this intentional ?
This is normal.
To build the module, on the host do: (you will need to change the paths, to suit your installation)
rgetz@home:~/uClinux-dist> make -C /home/uClinux-dist/linux-2.6.x SUBDIRS=/home/module_example modules make: Entering directory `/home/uClinux-dist/linux-2.6.x' CC [M] /home/module_example/sample_module.o Building modules, stage 2. MODPOST CC /home/module_example/sample_module.mod.o LD [M] /home/module_example/sample_module.ko make: Leaving directory `/home/uClinux-dist/linux-2.6.x'
This will leave a few new files in the /home/module_example
directory
rgetz@home:~/uClinux-dist> ls -l /home/module_example total 24 -rw-r--r-- 1 rgetz users 25 2005-09-28 19:14 Makefile -rw-r--r-- 1 rgetz users 862 2005-09-28 19:13 sample_module.c -rw-r--r-- 1 rgetz users 2682 2005-09-28 19:18 sample_module.ko -rw-r--r-- 1 rgetz users 454 2005-09-28 19:18 sample_module.mod.c -rw-r--r-- 1 rgetz users 1248 2005-09-28 19:18 sample_module.mod.o -rw-r--r-- 1 rgetz users 1944 2005-09-28 19:18 sample_module.o
sample_module.o
is the object file of the module, this can not be loaded into the kernel.
sample_module.ko
is the kernel module, it is the file which can be dynamically loaded and unloaded from the kernel.
rgetz@home:~module_example> file sample_module.ko sample_module.ko: ELF 32-bit LSB relocatable, version 1 (SYSV), not stripped
sample_module.mod.c
is generated by kernel Makefile automatically. It defines where to link the module initialization and dependency data.
root:~> lsmod Module Size Used by lsmod: /proc/modules: No such file or directory
or by checking the /proc/modules
directory
root:~> ls /proc/modules ls: /proc/modules: No such file or directory
If you are running a kernel which supports loadable modules, you should see something that looks like:
root:~> lsmod Module Size Used by root:~> ls -l /proc/modules -r--r--r-- 1 0 0 0 /proc/modules
root:~> insmod ./sample_module.ko root:~> lsmod Module Size Used by sample_module 1396 0 - Live 0x00653000
root:~> rmmod sample_module
root:~> lsmod Module Size Used by
If you want to have initialization parameters that you can change at runtime, you need to use some helper functions.
Here we'll create a long variable named delay
.
static long delay = 5; module_param(delay, long, 0); MODULE_PARM_DESC(delay, "number of seconds to delay before firing; default = 5 seconds");
Then to change it while loading the module, simply use:
root:~> modprobe sample_module delay=14
Information about kernel modules are exported via the sysfs
filesystem which is typically mounted at /sys.
Please see the parameters page for manipulating parameters at runtime.
To find out where module sections are loaded at runtime, look in the sections subdirectory:
root:~> insmod sample_module root:~> ls -a /sys/modules/sample_module/sections/ . .init.text .. .rodata .bss .rodata.str1.4 .data .strtab .exit.text .symtab .gnu.linkonce.this_module .text root:~> cat /sys/modules/sample_module/sections/.data 0x3221078 root:~> cat /sys/modules/sample_module/sections/.text 0x3220000
This tells us that the .data
section of the module is mapped at the address 0x3221078
and that the .text
section of the module is mapped at the address 0x3220000
.
If you wish to link the module directly into the kernel, you should not need to change any of the code. The __init
directive in the function definition as well as themodule_init()
will setup the proper code so that your initialization function is called when the kernel boots.
By default, module_init()
will be defined as a device_initcall()
. If your driver is not a device, you may need to use another call:
core_initcall(fn) postcore_initcall(fn) arch_initcall(fn) subsys_initcall(fn) fs_initcall(fn) device_initcall(fn) late_initcall(fn)
The Makefile will need a slight tweak. Rather than using 'obj-m', the variable you want is 'obj-y'.