1. Hello
World module
To construct a 2.6.x kernel module, you must configure and construct the kernel tree in your system. "Hello
The code of the world sample module is as follows:
# Include <Linux/init. h> <br/> # include <Linux/module. h> <br/> module_license ("GPL"); <br/> static int _ init hello_init (void) <br/>{< br/> printk (kern_alert "Hello, world/N"); <br/> return 0; <br/>}< br/> static void _ exit hello_exit (void) <br/>{< br/> printk (kern_alert "Goodbye, world/N "); <br/>}< br/> module_init (hello_init); <br/> module_exit (hello_exit );
Module_init and module_exit use special macros of the kernel to represent the roles played by hello_init and hello_exit. The special macro module_license is used to tell the kernel that the module adopts a free license. The module can call printk because the module is connected to the kernel after the insmode function is loaded into the module, so it can access the public symbols of the kernel. Of course, we can also use the rmmod tool to uninstall this module.
[Wzhwho @ local ~] # Insmod./Hello. Ko
Hello, world
[Wzhwho @ local ~] # Insmod./Hello. Ko
Goodbye, world
2. core modules and Applications
1) The application executes a single task from start to end. The module needs to register itself in advance to serve a future request, and its initialization function ends immediately.
2)
When an application exits, it can release resources or clear other tasks. However, the exit function of the module must carefully cancel all operations performed by the initialization function.
3)
An application can call undefined functions, because the connection process will parse external references and use the appropriate function library. The module is only connected to the kernel, the function that he can call is only a function exported from the kernel, and there is no function library that can be linked. In addition, printk does not support floating-point numbers. That is to say, kernel code does not support floating-point operations.
4)
Segment errors of applications are harmless; Module errors are not allowed.
5)
Applications are deployed in virtual memory and have a large stack space (Stack is used to save the function call history and the automatic variables in the current active function ); however, the kernel has a very small stack, which may be as large as a page of 4096 bytes. Therefore, in the kernel space, a large structure should be dynamically allocated during calling.
Modular code runs in the kernel space and is used to extend the functions of the kernel. The Linux kernel code (including the driver code) must be reentrant and must be able to run in multiple contexts at the same time. In section 2.6, kernel code (almost) Never assumes that the processor can be exclusive to a given code segment.
3. Compilation Module
To construct a 2.6.x kernel module, you must configure and construct the kernel tree in your system. The following is
Makefile extension syntax writing rules.
OBJ-M: = Hello. o
This statement indicates that a module needs to be constructed from the target file hello. O, and the module name constructed from the target file is hello. Ko.
If the module name to be constructed is module. Ko, which is generated by two source files, the correct makefile is written as follows:
OBJ-M: = module. o
Module-objs: = file1.o file2.o
To make makefiles of this type work normally, you must call them in a large kernel construction system environment. If the kernel source code tree is stored in ~ In the/kernel-2.6.18 directory, the make command used to construct the module should be (in the directory containing the module source code and makefile ):
Make-C ~ // Kernel-2.6.18 M = 'pwd' modules
The above command first changes the directory to the location specified by the-C option (that is, the kernel source code directory), where the top-level MAKEFILE file of the kernel is saved. The M = option allows the makefile to return to the module source code directory before constructing the modules target. Then, the modules target points to the module set in the obj-m variable.
The following provides a method to make it easier to construct modules outside the kernel tree. As follows:
Ifneq ($ (kernelrelease ))
OBJ-M: =
Hello. o
Else
Kerneldir? =
/Lib/moduels/$ (shell uname-R)/build
PWD: = $ (Shell
PWD)
Default:
$ (Make)-C $ (kerneldir)
M = $ (PWD) Modules
Endif
4. Load and unload modules
The tool insmod loads the module code and data into the kernel, and then uses the kernel symbol table to parse any unparsed symbols in the module. Unlike the connector, the kernel does not modify the disk files of the module, but only modifies the copies in the memory. The tool insmode is defined as a system call in kernel/module. C. The names are prefixed with sys.
The modprobe tool differs from insmod in that it considers whether the module to be loaded references symbols that do not exist in the current kernel. If such references exist, modprobe searches for other modules that define these symbols in the current search path. If modprobe finds these modules, it will simultaneously load these modules to the kernel.
The rmmod tool removes modules from the kernel. If the kernel considers that the module is still in use (a program is opening the device file exported by this module), or the kernel is configured to prohibit the removal of the module, the module cannot be removed.
The lsmod tool lists all modules currently loaded into the kernel. Read the/proc/modules Virtual File to obtain the information.
5. Version dependency and platform dependency
During the construction process, you can combine your module with a file in the current kernel tree (vermagic. o) link; the target file contains information about the kernel, including the target kernel version, compiler version, and settings of some important configuration variables. When trying to load a module, this information can be used to check the compatibility between the module and the running kernel.
6. kernel symbol table
The kernel symbol table contains the addresses of all global kernel items (functions and variables), which is required to implement modular drivers. If a module needs to export symbols from other modules, use the following macro:
Export_symbol (name );
Export_symbol_gpl (name );
The _ GPL version allows the module to be exported to be used only by the module under the GPL license. The symbol must be exported globally in the module File and cannot be exported in the function. The exported symbol is extended to a special variable, which must be global. This variable is saved in a special part of the module executable file (an elf segment). During loading, the kernel searches for the variables exported by the module through this segment.
7. Initialization and Shutdown
7.1. Initialization
The initialization function of the module registers any facility required by the module. It should be declared as static because such a function has no meaning other than a specific file. The initialization mark (_ init) is a hint to the kernel, indicating that this function is only used during initialization. After the module is loaded, the module loader will discard the initialization function and release the memory. _ Init and _ initdata are optional, while _ devinit and _ devinidata are translated by the kernel only when the kernel is not configured to support hot swapping devices.
7.2. Clear the Function
Each important module requires a clearing function to release the resources occupied by the module in the system. The cleanup function has no return value. The __exit modifier marks that the code is only used for module uninstallation (the compiler places the function in a special elf field ).
7.3. handle errors during initialization
If you encounter any errors when registering a facility, you must first determine whether the module can continue initialization. Generally, after a registration fails, you can downgrade the function to continue running. If the module cannot be loaded after a specific error occurs, cancel any previous registration. The purge function of the module needs to install the registration location to cancel all facilities in reverse order. When an error occurs, you can use the GOTO statement to improve efficiency. (If you do not use the GOTO statement, you have to record the status of the facility registration. When you call the clearing function, it usually requires more code and CPU time ).
Struct something * Item1; <br/> struct somethingelse * item2; <br/> int hello_ OK; <br/> void hello_cleanup (void) <br/>{< br/> If (Item1) <br/> release_thing (Item1); <br/> If (Item1) <br/> release_thingelse (Item1 ); <br/> If (hello_ OK) <br/> unregister_hello (hello_ OK); <br/> return; <br/>}< br/> static int _ init hello_init (void) <br/>{< br/> int err =-enomem; <br/> Item1 = allocate_thing (arguments1) <br/> Item1 = allocate_thingelse (arguments2) <br/> If (! Item1 |! Item2) <br/> goto out; <br/> err = register_hello (Item1, item2) <br/> If (! Err) <br/> hello_ OK = 1; <br/> else <br/> goto out; <br/> return 0; <br/> out: <br/> hello_cleanup (); <br/> return err; <br/>}
7.4. Module Parameters
The module parameters need to change due to different systems. The module parameters can be assigned when running the insmod or modprobe command to load the module, while modprobe can also read the parameter values from its configuration file (/etc/modprobe. conf. We add two parameters to the hello World module: an integer named howm and a string named whom. When loading the module, we will greet whom for howmany times. Run the following command:
[Wzhwho @ local ~] # Insmod
Hello howm = 10 whom = "wzhwho"
Of course, before insmod changes the module parameters, the module must make these parameters visible to the insmod command. The parameter must be declared using the module_param macro, which is defined in <moduleparam. h>. Module_param requires three parameters: the variable name, type, and the access license mask of the user sysfs entry. In hello. C:
Static char * Whom = "wzhwho ";
Static int howtasks = 1;
Module_param (howmany, Int, s_irugo );
Module_param (whom, CHARP, s_irugo );
The module loader supports array parameters. When providing array values, use commas to divide the array members. The parameters of the array to be declared are as follows:
Module_param (name, type, num, Perm );
The last member in module_param is the access permission value, which is defined in <Linux/STAT. h>. If perm is set to 0, there will be no corresponding sysfs entry; otherwise, the module parameters will appear in/sys/module and the given access permission will be set. If s_irugo is used for a parameter, anyone can read the parameter but cannot modify it. s_irugo | s_iwusr allows the root user to modify the parameter.