Loadable Kernel Modules Kevin Dankwardt, Ph.D. kevin.dankwardt@gmail.com
Topics 1. Why loadable kernel modules? 2. Using Modules 3. Writing modules 4. Compiling & Installing Modules 5. Example : Simple Module 6. Command line parameters 7. Modules are not binary compatible with different kernels 8. vermagic 9. tainting 10. modinfo 11. Export symbols 12. Stacking Modules 13. kernel/module.c 14. kernel/kmod.c 15. scripts/makefile.modpost 16. Statically linked modules 17. References etc
Why Loadable Kernel Modules Makes booting kernel smaller and faster Need to include just functionality, like drivers, that one needs. Faster and easier to update functionality No need to reboot to add or remove functionality Note that removing is dangerous and maybe you shouldn't do it.
Using modules insmod modprobe lsmod depmod modinfo rmmod weak-modules make modules available for more than one kernel version (yikes)
Writing modules Modules require many header files, e.g., #include <linux/module.h> #include <linux/sched.h> These header files will come from the kernel source directory. Use module_init() and module_exit() macros. Use MODULE_LICENSE() macro.
Compiling & Installing Modules make modules # in kernel source directory make make modules_install Or, for your own directory: make -C /lib/modules/$(uname -r)/build M=$PWD modules make modules_install INSTALL_MOD_PATH=~kevin/myrootfs Makefile: obj-m := := mod.o
# cat simplemodule.c #include <linux/init.h> #include <linux/module.h> #include <linux/sched.h> int init_simple(void) { printk("in init module simple\n"); return 0; } void cleanup_simple (void) { printk ("in cleanup module simple\n"); } module_init(init_simple); module_exit(cleanup_simple); MODULE_LICENSE("GPL"); # echo obj-m := simplemodule.o > Makefile Example : Simple Module # make -C /lib/modules/$(uname -r)/build M=$PWD modules # insmod./simplemodule.ko # rmmod simplemodule # dmesg tail
Command line parameters insmod module.ko parm=value module_param(name, type, permissions) module_param_array(name, type, number, perm) MODULE_PARM_DESC() Module parameters are listed in /sys/module under the module name if perm is non-zero.
Modules are not binary compatible with different kernels struct S { int f1; int f1b; int f2; } thes; module.c... thes.f2 = 5; Will module.o be portable if f1b is added or removed?
vermagic include/linux/vermagic.h Checks for SMP, PREEMPT, MODULE_UNLOAD, MODVERSIONS Includes UTS_RELEASE and strings based on the above. Although what is in vermagic is kernel version dependent. Different than just the kernel version (UTS_RELEASE). (UTS comes from Unix Timesharing System, and is related to uname(2).) Use modinfo <modulename> to see an example vermagic string vermagic is put into vmlinux (in its Read only Data section), (see include/asmgeneric/vmlinux.lds.h, for example) vermagic is put into each module via:q scripts/mod/modpost.c Kernel compares vermagic when loading the module: sys_init_module () load_module() if (!same_magic(modmagic, vermagic, versindex)) { printk(kern_err "%s: version magic '%s' should be '%s'\n", mod->name, modmagic, vermagic); err = -ENOEXEC; goto free_hdr;
Tainting Tainting is used to indicate that a non GPL (open source) module was loaded. If ndiswrapper is used, the kernel is tainted. If driverloader was used, the kernel is tainted Forcing loading or unloading of modules Module is proprietary - i.e., not GPL
modinfo modinfo <module name> author, description, license, parm, depends, and alias modprobe uses the depends info in files created by depmod
Export Symbols To register entries in the symbol table: Add driver code to kernel source Use EXPORT_SYMBOL(symbol) to export symbol EXPORT_SYMBOL_GPL(symbol) to restrict symbol use to only GPL d modules.
Stacking Modules Modules link to symbols and can provide symbols that other modules require. A module that uses symbols from another module, depends on that module. These modules form a stack. modpost puts depends info in the modinfo section
kernel/module.c 3100+ LOC Does tainting Handle module reference counting Resolve symbols
kernel/kmod.c request_module() macro request_module() calls this about 175 calls to request_module() in the kernel Allows for the kernel to quest a module to be loaded invokes a user space helper e.g. modprobe to load the module
scripts/makefile.modpost # Stage one of module building created the following: # a) The individual.o files used for the module # b) A <module>.o file which is the.o files above linked together # c) A <module>.mod file in $(MODVERDIR)/, listing the name of the # the preliminary <module>.o file, plus all.o files # Stage 2 is handled by this file and does the following # 1) Find all modules from the files listed in $(MODVERDIR)/ # 2) modpost is then used to # 3) create one <module>.mod.c file pr. module # 4) create one Module.symvers file with CRC for all exported symbols # 5) compile all <module>.mod.c files # 6) final link of the module to a <module.ko> (or <module.unsigned>) file # 7) signs the modules to a <module.ko> file # Step 3 is used to place certain information in the module's ELF # section, including information such as: # Version magic (see include/vermagic.h for full details) # - Kernel release # - SMP is CONFIG_SMP # - PREEMPT is CONFIG_PREEMPT # - GCC Version # Module info # - Module version (MODULE_VERSION) # - Module alias'es (MODULE_ALIAS) # - Module license (MODULE_LICENSE) # - See include/linux/module.h for more details
Statically Linked Drivers Add driver code to kernel source Mark initialization function with module_init() Modify the file Makefile in the same directory as your driver code by adding: obj-y += your_code.o
References etc http://tldp.org/howto/module-howto scripts/makefile.modpost kernel source code Contact Contact Kevin Kevin Dankwardt Dankwardt for for info info on on consulting consulting and and training. training. kevin.dankwardt@gmail.com Kernel Kernel internals internals Device Device driver driver development Application development Debugging Debugging Performance Virtualization Embedded Embedded Linux Linux System System admin admin