Module Example

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.

sample_module.c

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);

Makefile

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

Building a Kernel with module support

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.

Building the Module

To build the module, on the host do: (you will need to change the paths, to suit your installation)

Before following the next steps, it is assumed that your kernel is configured for your system. If it is not configured properly, you will run into errors.

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.

Using the Module

  1. After the kernel is booted, make sure you are running a kernel which supports modules, This can be done by:
    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
  2. Load the module to the target, via network (ftp, rcp, nfs, wget) or serial (if you have compiled in zmodem support)
  3. Install the module
    root:~> insmod ./sample_module.ko
    root:~> lsmod
    Module                  Size  Used by
    sample_module 1396 0 - Live 0x00653000
  4. This is only a sample module framework. It does nothing. If you want it to do anything, please add specific code into it.
  5. Remove the module
    root:~> rmmod sample_module
  6. Make sure the module is gone:
    root:~> lsmod
    Module                  Size  Used by

Module Parameters

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

Extracting information at runtime

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.

Building the module into the kernel

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'.


你可能感兴趣的:(Module Example)