Linux Modules Character drivers IO & Memory Linux Kernel Process Management Process Address space Linux Scheduler Memory Management Interrupts Signals System Calls Kernel Synchronization Linux Inter Process Communications Serial Ports Parallel Ports Introduction to Hardware Linux Timers DMA in Linux Linux Threads Linux Thread Synchronization Linux Multi Threading Debugging in Linux GDB GNU Debugger KDB Kernel Debugger KGDB Kernel GNU Debugger Example Ethernet Driver |
Modules Each piece of code that can be added to the kernel at runtime is called a "module". The linux kernel offers support for quiet a few different types of modules, including, but not limited to device drivers. A module is "object code" (not linked to a complete executable) that can be dynamically linked to the running kernel and can be unlinked. Uses of Modules ü Allow third party commercial development of drivers ü Minimize kernel size ü Allow smaller generic kernels Modutils: insmod; modprobe; depmod; lsmod; modinfo; rmmod; ksyms; kerneld; insmod ü Installs a loadable module in the running kernel. ü
Load time parameters can be passed to the
module, to customize its operation ( eg. I/O ports, IRQ Nosetc) modprobe Uses a “makefile”-like dependency file (created by "depmod") to automatically load the relevant modules from the set of modules available in predefined directory trees. ü Used to load a module, either a single module, a stack of dependent modules ü Will try to load a module out of a list and stops loading as soon as one module loads successfully. depmod Makes a “Makefile”-like dependency file, which is later used by modprobe. lsmod Shows information about all loaded modules (name, size, use count, list of referring modules etc..) modinfo Displays information about a kernel module (from object file) rmmod Tries to unload a (set of ) module(s) from the running kernel with the restriction that they are not in use and that they are not referred to by other modules. hello module–initialization and cleanup /*
hello.c*/ #include
<linux/init.h> #include
<linux/module.h> #include
<linux/kernel.h> static
int__init hello_init(void) { printk(KERN_ALERT “Hello World\n"); return 0; } static void
__exit hello_exit(void) { printk(KERN_ALERT “Good Bye!\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Greeting
module"); MODULE_AUTHOR(“B
R Sahu”); __init: removed after initialization (static kernel or module). __exit: discarded when module compiled statically into the kernel. Compiling kernel modules Kernel modules need to be compiled with certain gcc options to make them work. The 2.6 compatible Makefilefor the module testmod.ko obj-m
:= testmod.o A simple command line for building a module #make –C
/usr/src/linux-2.6.1 SUBDIRS=$PWD modules Assumes, your module‟s source code and Makefile are located at the same directory Compiling a module The below Makefile should be reusable for any Linux 2.6 module. Just run make to build the hello.ko file Caution: make sure there is a [Tab] character at the beginning of the $(MAKE) line (make syntax) # Makefile for the hello module obj-m := hello.o KDIR := /lib/modules/$(shell uname-r)/build** PWD := $(shell pwd) default: *$(MAKE) –C $(KDIR) SUBDIRS=$(PWD) modules *[Tab]!(no spaces) **either -Full kernel source directory (configured and compiled) -or just kernel headers directory (minimum needed) Running module You can test the module by calling insmod and rmmod (Note that only super-user can load and unload a module). root# insmod./hello.o Hello, World root# rmmod hello Goodbye # ü You can verify the loading of modules using lsmod. ü The messages appear only on the console, not on xconsole. ü Take a look at /var/log/messages just to see that it got logged toyour system logfile. Linking a module to the kernel Application vs Module ü An application performs a single task from beginning to end. ü A module registers itself in order to serve future requests and its “main” function i.e., init_module terminates immediately. ü The second entry point of a module, “cleanup_module” gets invoked just before the module is unloaded by rmmod etc. ü A module is linked only to the kernel and the only functions it can call are the ones exported by the kernel. A module is not linked to any standard library like libc etc. Usage Count The system keeps a usage count for every module in order to determine whether the module can be safely removed. For example you can remove a filesystem type while the filesystem is mounted. To work with the usage count, use these three macros: MOD_INC_USE_COUNT: Increments the count for the current module MOD_DEC_USE_COUNT: Decrements the count MOD_IN_USE: Evaluates to true if the count is not zero Module Configuration Parameters Several parameters that a driver needs to know can change from system to system. Parameter values can be assigned at load time by insmod. The command accepts the specification of integer and string values on the command line. Thus, if your module were to provide an integer parameter called ival and a string parameter called sval, the parameters could be set at module load time with an insmod command like: #insmod
hello.oival=200 sval=”Welcome” However, before insmod can change module parameters, the module must make them available. Parameters are declared with the MODULE_PARM macro, which is defined in module.h. MODULE_PARM takes two parameters: the name of the variable and a string describing its type. The macro should be placed outside of any function and is typically found near the head of the source file. The two parameters mentioned earlier could be declared with the following lines: intival=0; char *sval; MODULE_PARM(ival,
“i”); MODULE_PARM(sval,
“s”); /*
module2.c */ #include
<linux/module.h> #include
<linux/moduleparam.h> #include
<linux/init.h> int ival=0; char *sval; module_param(ival,
int, S_IRUGO); module_param(sval,
charp, S_IRUGO); int my_init(void)
//module entry point { printk("#=== Module Initialized ===#\n");
//kernel print function printk("ival= %d\n val=%s\n", ival, sval);
//kernel print function return 0; } void
my_exit(void) //cleanup function { printk("#=== Module removed ===#\n"); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); Exporting Symbols A module implements its own functionality without the need to export any symbols. You will need to export symbols, whenever other modules may benefit from using them. You may also need to include specific instructions to avoid exporting all non-static symbols, as most versions of modutils export all of them by default. The Linux kernel header files provide a convenient way to manage the visibility of your symbols, thus reducing namespace pollution and promoting proper information hiding. If your module exports no symbols at all, you might want to make that explicit by placing a line with this macro call in source file: EXPORT_NO_SYMBOLS; Creating stacked loadable modules You can stack new modules on top of other modules, and new modules can use symbols exported by your module. Module stacking is implemented in the main stream kernel sources as well: each input USB device module stacks on the usbcore and input modules. Module stacking is useful in complex projects. If a new abstraction is implemented in the form of a device driver, it might offer a plug for hardware-specific implementations Stacking of parallel port driver modules Module
Implementation Modules are stored in the filesystem as ELF object files. Module is loaded into RAM by /sbin/insmod. The kernel allocates memory area containing the following data: ü A module object ü A null-terminated string that represents the name of the module. ü The code that implements the functions of the module. The module object describes a module. A simple linked list collects all module objects. The first element of the list is addressed by the module_list variable. Module
Object size_of_struct: size of module object next: next list element name: pointer to module name size: module size uc.usecount: module usage counter flags: module flags nsyms: number of exported symbols ndeps: number of referenced modules syms: table of exported symbols deps: list of referenced modules refs: list of referencing modules init: initialization method cleanup: cleanup method ex_table_start: start of exception table ex_table_end: end of exception table Linking
and unlinking modules A user can link a module into running kernel by executing /sbin/insmod: 1. Reads the name of module from the command line 2. Locates the file containing module’s object code 3. Computes the size of memory area needed 4. Invokes the create_module() system call 5. Invokes the query_module() system call 6. Using the kernel symbol table, relocates object code included in the module’s file 7. Allocates a memory area in the user mode address space, loads it with a copy of the module object. Sets init and cleanup fields. 8. Invokes the init_module() 9. Releases the user mode memory area and terminates. Linking
and unlinking modules… A user can unlink a module from running kernel by executing /sbin/rmmod: 1. Reads the name of module from the command line 2. Invokes the query_module() system call to get list of linked modules. 3. Invokes the query_module() system call to retrieve dependency information. 4. Invokes the delete_module() system call, passing the module’s name. |