Linux kernel module programming and Kernel module license-pre-read "Specific explanation (3rd edition)"

Source: Internet
Author: User
Tags wrapper

The Linux kernel module provides a simple introduction to the overall architecture of the Linux kernel, which is already large and includes components or many more. How do we include the required parts in the kernel?
One way is to compile all the required functions into the Linux kernel. This can cause two problems. One is that the generated kernel will be large, and the second is that we will have to compile the kernel again if we want to add or remove features from the existing kernel.


Is there a mechanism that the compiled kernel itself does not need to include all of its functions, and that the corresponding code is dynamically loaded into the kernel when these functions need to be used?
Linux provides such a mechanism, which is called a module. The module has such characteristics.

    1. The module itself is not compiled into the kernel image, which controls the size of the kernel.

    2. Once the module is loaded, it is exactly the same as the rest of the kernel.
To make the reader's initial perceptual knowledge of the module, let's look at one of the simplest kernel modules, "Hello World", as seen in code listing 4.1.


Code Listing 4.1 One of the simplest Linux kernel modules

/*02  * A simple kernel module:hello03  *04  * Copyright (C) Barry Song  ([email protected])  *0 6  * Licensed under GPLv2 or later.07  */0809 #include <linux/init.h>10 #include <linux/module.h>1112 The static int __init hello_init (void) is {     printk (kern_info "Hello World enter\n"), and the     return 0;16}17 module_init ( Hello_init) 1819 static void __exit hello_exit (void), PRINTK kern_info     (exit\n "Hello World}23"); (hello_exit), 2425 module_author ("Barry Song <[email protected]>"), Module_license ("GPL v2"), Module_ DESCRIPTION ("A Simple Hello World module"), Module_alias ("A simplest module");

This simplest kernel module includes only kernel module loading functions, unload functions, and statements about GPL v2 permissions and some descriptive narrative information. The book is located in the supporting source/kernel/drivers/hello folder. Compiling it produces a Hello.ko target file that can be loaded with the "Insmod./hello.ko" command, which can be unloaded by the "rmmod Hello" command, which outputs "Hello World enter" on load, and "Hello World" when unloaded Exit ".


The function used in the kernel module for output is the PRINTK () of the kernel space rather than the user space of printf (). The use of PRINTK () is basically similar to printf (), but the former defines the output level. PRINTK () can be used as one of the most important kernel debugging methods, which will be explained in detail in the Linux Driver Debugging section.
In Linux. Use the Lsmod command to get all the modules loaded in the system and the dependencies between the modules, such as:

Module                  Size  used Byhello                   9 472  0nls_iso8859_1          032 1nls_cp437              1vfat 696                   816  1fat                    376  1 Vfat ...

The lsmod command actually reads and parses the "/proc/modules" file. The "/proc/modules" file corresponding to the above lsmod command result is as follows:
$ Cat/proc/moduleshello 12393 0-live 0xe67a2000 (OF) Nls_utf8 12493 1-live 0xe678e000isofs 39596 1-live 0xe677f000vb oxsf 42561 2-live 0xe6767000 (OF) ...
The information that is loaded into the module in the kernel also exists under the/sys/module folder. After loading Hello.ko, the/sys/module/hello folder will be included in the kernel. This folder also includes a refcnt file and a sections folder, under the/sys/module/hello folder to perform "Tree–a" to get such as the following folder tree:
[Email protected]:/sys/module/hello# tree-a.├──coresize├──holders├──initsize├──initstate├──notes│   └──. note.gnu.build-id├──refcnt├──sections│   ├──.exit.text│   ├──.gnu.linkonce.this_module│   ├──.init.text│   ├──.note.gnu.build-id│   ├──.rodata.str1.1│   ├──.strtab│   └──.symtab├──srcversion├──taint└── Uevent3 directories, files

Modprobe commands are stronger than INSMOD commands. When it loads a module, it loads the other modules on which the module depends.

The module loaded with the Modprobe command unloads the module it relies on at the same time as "Modprobe-r filename". The dependencies between modules are stored in the/lib/modules/<kernel-version>/modules.dep file of the root filesystem, which is actually generated by the Depmod tool when the kernel is compiled in its entirety, and its format is easy:

kernel/lib/cpu-notifier-error-inject.ko:kernel/lib/notifier-error-inject.kokernel/lib/ Pm-notifier-error-inject.ko:kernel/lib/notifier-error-inject.kokernel/lib/lru_cache.ko:kernel/lib/cordic.ko: kernel/lib/rbtree_test.ko:kernel/lib/interval_tree_test.ko:updates/dkms/vboxvideo.ko:kernel/drivers/gpu/drm/ Drm.ko

Use the Modinfo < module name > command to obtain information about the module, including the module author, the module's description, the module's supported parameters, and the vermagic:
# modinfo Hello.kofilename:       hello.koalias:          A simplest moduledescription:    a simple Hello World Modulelicense:        GPL v2author:         Barry Song <[email protected]>srcversion:     081230411494509792bd4a3depends:        vermagic:       3.8.0-39-generic SMP mod_unload modversions 686

Linux kernel module program structure a Linux kernel module consists of several parts, such as the following.
(1) Module loading function
When a kernel module is loaded via the Insmod or modprobe command. The loading function of the module will be executed by the kernel itself, and the related initialization of this module is completed.
(2) Module unload function
When a module is unloaded via the Rmmod command, the Unload function of the module is executed by the kernel itself, and the function opposite to the module unload function is completed.
(3) Module License Statement
The license (LICENSE) statement describes the license permissions of the kernel module, assuming that the LICENSE is not declared and that the module is loaded and will receive a warning that the kernel is contaminated (kernel tainted).
In the field of Linux kernel modules. Acceptable license include "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", "Dual MPL/GPL" and "proprietary" (This is controversial in both academia and the legal profession about whether modules can be used for non-GPL licenses such as "proprietary").
In most cases, the kernel module should follow the GPL-compatible license.

The most common Linux kernel modules are module_license ("GPL v2") statements that declare modules using the GPL v2.
(4) module parameters (optional).
The module parameter is the value that can be passed to a module when it is loaded, and it itself is the global variable within the module.
(5) module export symbol (optional).
The kernel module is able to export symbols (symbol. corresponding to a function or variable) so that other modules can use the variables or functions in this module.
(6) Information statements such as module authors (optional).

Module load function The Linux kernel module load function is typically declared with the _ _init identity, and a typical module load function is shown in the form of code listing 4.2.


Code Listing 4.2 Kernel module loading function

1     Static int _ _init initialization_function (void) 2     {    3/         * Initialization code */4     }5     module_init ( Initialization_function);

The module loading function is specified in the form of "module_init (function name)". It returns an integer value that, if initialized successfully, should return 0. In the case of initialization failure, an error encoding should be returned.

In the Linux kernel, the error code is a negative value close to 0, defined in <linux/errno.h>. This includes symbolic values such as-enodev,-enomem, and so on.

It's a good habit to always return the appropriate error code. Because of this, the user program is capable of using perror and other methods to convert them into meaningful error message strings.
In the Linux kernel, the ability to use Request_module (const char *FMT, ...) function is loaded into the kernel module, which drives the developer to call
Request_module (module_name);
Such a flexible way to load other kernel modules.


In Linux, functions identified as _ _init are assumed to be compiled directly into the kernel and become part of the kernel image, which is placed in the. Init.text section when connected.
#define _ _init _ _attribute_ _ ((_ _section_ _ (". Init.text")))
All the _ _init functions in the section. Initcall.init also holds a function pointer, which is called by the kernel through these function pointers at initialization time, and releases the Init section (including. Init.text, after initialization). Initcall.init, etc.) of memory.
In addition to functions, the data can also be defined as _ _initdata, and the kernel will be able to free up the memory it consumes after initialization for only the data that is required for the initialization phase. For example, the following code defines hello_data as __initdata.

static int Hello_data __initdata = 1;static int __init hello_init (void) {    printk (kern_info "Hello, World%d\n", hello_d ATA);    return 0;} Module_init (hello_init); static void __exit hello_exit (void) {    printk (kern_info "Goodbye, world\n");} Module_exit (Hello_exit);

Module Unload function
The Linux kernel module load function is typically declared as _ _exit, and a typical module unload function is shown in the form of code listing 4.3.
Code listing 4.3 kernel module unload function
1    static void _ _exit cleanup_function (void) 2    {3/          * Release code */4    }5    module_exit (cleanup_function);

The module unload function executes when the module is unloaded and does not return whatever value it must be specified in the form "module_exit (function name)". In general, the function of the module unload function is the opposite of the module loading function.


We use the __exit to modify the module unload function, can tell the kernel assumes that the relevant module is directly compiled into the kernel (i.e., built-in), then the Cleanup_function () function will be omitted directly not connected into the last mirror. Since the module is built-in. It's impossible to unload it. There is no need to unload a function. In addition to functions, data that is used only in the exit phase can be described by __exitdata.

Module Number of references
We are able to define a parameter for the module with "Module_param (number of parameters, type of reference, read/write permission)". The scale defines 1 integer and 1-character pointer parameters in the following code:

static char *book_name = "Dissecting Linux Device Driver"; Module_param (Book_name, Charp, s_irugo); static int book_num = 40 00;module_param (book_num, int, s_irugo);

When the kernel module is loaded, the user is able to pass the parameters to the module. The form is "Insmode (or modprobe) module Name parameter = Reference", assuming that it is not passed, the parameter will use the default value defined within the module. Assume that the module is built-in. Cannot be insmod, but bootloader can pass the parameters to the built-in module by setting the module name in the Bootargs.
The parameter type can be byte, short, ushort, int, uint, long, ulong, charp (character pointer), bool, or Invbool (Boolean inverse), which will be module_ when the module is compiled. The type declared in Param is compared to the type defined by the variable. Inference is consistent.
In addition, the module can also have an array of parameters, in the form of "Module_param_array (array name, array type, number leader, read/write permission)".
After the module is loaded, a folder named after the module name will appear under the/sys/module/folder. When "read/write permission" is 0 o'clock. Indicates that this parameter does not exist for the corresponding file node under the Sysfs file system. Assuming that this module has a command-line parameter of not 0 for read/write permission, the Parameters folder will also appear under the folder in this module. Includes a series of file nodes named after the name of the file, the permission value of which is the "read/write permission" of the Incoming Module_param (), and the content of the file is the value of the parameter.
When you execute the insmod or modprobe command, you should separate the input array elements with commas.
Now we define a module that includes two parameters, such as code listing 4.4. It is located in the source/kernel/drivers/param folder of this book, and the output of the module is passed when it is loaded and the parameter is not passed.


Code Listing 4.4 kernel modules with parameters

#include <linux/init.h>02 #include <linux/module.h>0304 static char *book_name = "Dissecting Linux Device D River "; Module_param (Book_name, Charp, S_irugo); 0607 static int book_num = 4000;08 Module_param (book_num, int, s_irugo) ; 0910 static int __init book_init (void) One {     printk (kern_info "book name:%s\n", Book_name); PRINTK     (Kern_ INFO "book num:%d\n", Book_num);     return 0;15}16 module_init (book_init); 1718 static void __exit book_exit (void) 19 {      PRINTK (kern_info "book Module exit\n"),}22 module_exit (book_exit); 2324 module_author ("Barry Song <[email Protected]> "), Module_license (" GPL v2 "), and Module_description (" A Simple module for testing module params "); 27 Module_version ("V1.0");

The "insmod Book.ko" command is loaded for the above modules, and the corresponding output is the default value within the module. You can see the output of the kernel by looking at the "/var/log/messages" log file:
# tail-n 2/var/log/messagesjul  2 01:03:10 localhost kernel:  <6> book name:dissecting Linux Device Driverju L  2 01:03:10 localhost kernel: book  num:4000

When the user executes the "insmod Book.ko book_name= ' goodbook ' book_num=5000" command. The output is the number of user-passed references:
# tail-n 2/var/log/messagesjul  2 01:06:21 localhost kernel:  <6> book Name:goodbookjul  2 01:06:21 Loca Lhost kernel: Book  num:5000jul 2 01:06:21 localhost kernel:book num:5000
Also, under the/sys folder, you can see the parameters of the book module:
[Email protected]:/sys/module/book/parameters$ tree.├──book_name└──book_num
Export Symbols Linux's "/proc/kallsyms" file corresponds to the kernel symbol table, which records the symbol and the memory address where the symbol resides.
The module can export symbols to the kernel symbol table using the following macros, for example:
Export_symbol (symbol name);
EXPORT_SYMBOL_GPL (symbol name);
The exported symbols will be able to be used by other modules. Declare it before you use it. EXPORT_SYMBOL_GPL () applies only to modules that include the GPL license. Code Listing 4.5 shows an example of a kernel module that exports integer plus and minus operation function symbols.
Symbol Export in Code listing 4.5 kernel modules
#include <linux/init.h>02 #include <linux/module.h>0304 int add_integar (int a, int b)     b;07}08 EXPORT_SYMBOL_GPL (add_integar); 0910 int Sub_integar (int a, int b) One {     return a-b;13}14 EXPORT_SYMBOL_GPL (Sub_integar); 1516 Module_license ("GPL v2");

Find information about Add_integar and Sub_integar from the "/proc/kallsyms" file:
# grep integar/proc/kallsymse679402c R __ksymtab_sub_integar    [export_symb]e679403c R __kstrtab_sub_integar    [ export_symb]e6794038 r __kcrctab_sub_integar    [export_symb]e6794024 R __ksymtab_add_integar    [EXPORT_SYMB] e6794048 r __kstrtab_add_integar    [export_symb]e6794034 R __kcrctab_add_integar    [export_symb]e6793000 t add_ Integar    [export_symb]e6793010 t Sub_integar    [EXPORT_SYMB]

Module declaration and descriptive narration
In the Linux kernel module, we can use Module_author, module_description, Module_version, module_device_table, Module_alias respectively to declare the author of the module, Descriptive narratives, version numbers, device tables, and aliases, such as:
Module_author (AUTHOR); Module_description (DESCRIPTION); Module_version (version_string); Module_device_table (Table_info); Module_alias (Alternate_name);

For USB, PCI and other device drivers, a module_device_table is typically created. Indicates the device supported by the driver module, as seen in Listing 4.6.
List of devices supported by the Code listing 4.6 driver
1/* the device table corresponding to this drive */2 static struct usb_device_id skel_table [] = {3 {usb_device (usb_skel_vendor_id,4       usb_skel_product_i D)},5     {}/* table end */6};78 module_device_table (USB, skel_table);

At this time The reader does not need to understand the role of module_device_table, perhaps the relevant chapters will be detailed.
Usage count of the module
Linux 2.4 kernel. The module itself manages the counts that are used by Mod_inc_use_count, Mod_dec_use_count macros.
After Linux 2.6, the kernel provides the module count management interface Try_module_get (&module) and Module_put (&module), which replaces the modules in the Linux 2.4 kernel using the Count management macros.

The usage count of a module is generally not necessarily managed by the module itself. and the module count management also considers the influence of SMP and preempt mechanism.



int try_module_get (struct module *module);

This function is used to add a module usage count. If the return is 0. Indicates that the call failed and that the module you want to use is not loaded or is being uninstalled.

void Module_put (struct module *module);

This function is used to reduce the module usage count.
The introduction and use of Try_module_get () and Module_put () is closely related to the device model under the Linux 2.6 kernel.

After Linux 2.6, the kernel defines a struct module *owner domain for different types of devices, which is used to point to the module that manages this device. When you start using a device, the kernel uses Try_module_get (Dev->owner) to add the usage count of the owner module that manages the device, when the device is no longer in use. The kernel uses module_put (Dev->owner) to reduce the usage count of the owner module that manages this device.

This way, the module that manages this device cannot be uninstalled when the device is in use. Only when the device is no longer in use does the module agree to be uninstalled.


In the kernel after Linux 2.6, it is very rare for device drivers to call Try_module_get () and module_put () in person. Since the driver written by the developer is usually the owner module that supports a specific device, the count management of this device's owner module is implemented by the kernel's lower-level code, such as a bus driver or a core module shared by such devices. This simplifies device-driven development.



Compilation of modules

We can write a simple makefile for the template in Code Listing 4.1:

Kvers = $ (Shell uname-r) # Kernel Modulesobj-m + = hello.o# Specify flags for the module compilation. #EXTRA_CFLAGS =-g-o0bu Ild:kernel_moduleskernel_modules:      make-c/lib/modules/$ (kvers)/build m=$ (CURDIR) Modulesclean:      make-c/lib /modules/$ (kvers)/build m=$ (CURDIR) Clean

The makefile file should be located in the same folder as the source hello.c, and the extra_cflags=-g-o0 in the open can be Hello.ko module that includes debugging information. The module that executes the make command can be executed directly on the PC.
If a module includes multiple. c files (such as file1.c, file2.c), you should write the makefile in the following way, for example:
Obj-m: = MODULENAME.O
MODULENAME-OBJS: = FILE1.O file2.o

module and Gpllinux kernel There are 2 ways to export symbols to the module, one method is Export_symbol (). The second type of EXPORT_SYMBOL_GPL (). This is consistent with module A, which exports symbols to module B.
The Documentation/docbook/kernel-hacking.tmpl of the kernel clearly indicates that "the symbols exported by EXPORT_SYMBOL_GPL () can is only a seen by modules With a module_license () that specifies a GPL compatible LICENSE. " This shows that the kernel uses EXPORT_SYMBOL_GPL () to export the symbol is not able to be referenced by non-GPL modules.
Since quite a lot of the kernel symbols are exported in EXPORT_SYMBOL_GPL (), historically there have been companies that have changed the kernel's EXPORT_SYMBOL_GPL () directly to Export_symbol (). The modified kernel is then published in GPL form. After this changes the kernel, the module no longer uses the kernel's EXPORT_SYMBOL_GPL () symbol, so the module no longer requires the GPL. The reply to this Linus is: "I think both them said that anybody who were to change a XYZ_GPL to the NON-GPL one in order to use it with a NON-GPL module would almost immediately fall under the "willful infringement" thing, and that it would make it MUCH Easie R to get triple damages and/or injunctions, since they clearly knew about it ".

Thus, such an approach may constitute a "deliberate infringement (willful infringement)".
The second approach is to write a wrapper kernel module (this module follows the GPL). The EXPORT_SYMBOL_GPL () exported symbol is encapsulated once again in the form of Export_symbol (), while the other modules do not call the kernel directly but call the wrapper function. 4.1 of what you see. Such a practice is also controversial.

Figure 4.1 EXPORT_SYMBOL_GPL again with Export_symbol export
Generally feel. The conservative approach is that the Linux kernel cannot use non-GPL permissions.




Linux kernel module programming and Kernel module license-pre-read "Specific explanation (3rd edition)"

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.