Linux Kernel module programming and kernel module LICENSE

Source: Internet
Author: User

Introduction to the Linux kernel module the overall structure of the Linux kernel is already very large, and it contains many components. How can we include all the required parts in the kernel?
One way is to compile all required functions into the Linux kernel. This will cause two problems. One is that the generated kernel will be very large, and the other is that if we want to add or delete features in the existing kernel, we will have to re-compile the kernel.
Is there a mechanism that does not need to include all functions in the compiled kernel itself, but when these functions need to be used, the corresponding code is dynamically loaded into the kernel?
Linux provides such a mechanism called Module ). The module has such characteristics.
To help readers establish a preliminary understanding of the module, Let's first look at the simplest kernel module "Hello World", as shown in code list 4.1.
Code List 4.1 a simple Linux kernel module

01 /*02  * a simple kernel module: hello03  *04  * Copyright (C) 2014 Barry Song  (baohua@kernel.org)05  *06  * Licensed under GPLv2 or later.07  */0809 #include <linux/init.h>10 #include <linux/module.h>1112 static int __init hello_init(void)13 {14     printk(KERN_INFO "Hello World enter\n");15     return 0;16 }17 module_init(hello_init);1819 static void __exit hello_exit(void)20 {21     printk(KERN_INFO "Hello World exit\n ");22 }23 module_exit(hello_exit);2425 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");26 MODULE_LICENSE("GPL v2");27 MODULE_DESCRIPTION("A simple Hello World Module");28 MODULE_ALIAS("a simplest module");

This simplest kernel module only contains the declaration of kernel module Loading Function, uninstalling function, and GPL v2 permission and some descriptions, located in the/kernel/drivers/hello directory of the matching source code in this book. Compile it to generate hello. ko target file, through "insmod. /hello. the ko command can load it. You can run the "rmmod hello" command to uninstall it, and output "Hello World enter" during loading and "Hello World exit" during uninstallation ".
The functions used for output in the kernel module are the kernel space printk () instead of the user space printf (). The usage of printk () is similar to that of printf, however, the former can define the output level. Printk () can be used as the most basic kernel debugging method. This function is described in detail in the Linux driver debugging chapter.
In Linux, you can use the lsmod command to obtain all modules loaded in the system and their dependencies. For example:
Module                  Size  Used byhello                   9 472  0nls_iso8859_1          12 032  1nls_cp437              13 696  1vfat                   18 816  1fat                    57 376  1 vfat...

The lsmod Command actually reads and analyzes the "/proc/modules" file. The "/proc/modules" file corresponding to the preceding lsmod command result is as follows:
$ cat /proc/moduleshello 12393 0 - Live 0xe67a2000 (OF)nls_utf8 12493 1 - Live 0xe678e000isofs 39596 1 - Live 0xe677f000vboxsf 42561 2 - Live 0xe6767000 (OF)...
The information of the loaded modules in the kernel also exists in the/sys/module Directory, loading hello. after ko, the kernel will contain the/sys/module/hello Directory, which contains a refcnt file and a sections directory, run "tree-a" in the/sys/module/hello directory to obtain the following directory tree:
root@barry-VirtualBox:/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, 15 files

The modprobe command is more powerful than the insmod command. When a module is loaded, it loads other modules that the module depends on at the same time. If a module loaded using The modprobe command is uninstalled in "modprobe-r filename" mode, the module on which it depends will be uninstalled at the same time. The dependencies between modules are stored in/lib/modules/<kernel-version>/modules of the root file system. in the dep file, it is actually generated by the depmod tool during kernel compilation. Its format is very simple:
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 the module information, including the module author, module description, supported parameters, and vermagic:
# modinfo hello.kofilename:       hello.koalias:          a simplest moduledescription:    A simple Hello World Modulelicense:        GPL v2author:         Barry Song <21cnbao@gmail.com>srcversion:     081230411494509792BD4A3depends:        vermagic:       3.8.0-39-generic SMP mod_unload modversions 686

The program structure of the Linux kernel module consists of the following parts.
(1) module Loading Function
When the kernel module is loaded using the insmod or modprobe command, the module's loading function is automatically executed by the kernel to complete the initialization of this module.
(2) unmount a function
When you run the rmmod command to uninstall a module, the unmount function of the module is automatically executed by the kernel to complete the function opposite to the unmount function of the module.
(3) module license statement
The LICENSE declares the permission to describe the kernel module. If the LICENSE is not declared, the module will receive a warning of kernel contamination (kernel tainted) when it is loaded.
In the Linux kernel module field, acceptable licenses include "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", "Dual MPL/GPL", and "Proprietary" (about whether the module can use non-GPL permission such as "Proprietary ", this is controversial in academic and legal circles ).
In most cases, kernel modules should follow the GPL compatibility permission. The most common Linux kernel module is the gple_license ("GPL v2") Statement declaration module using GPL v2.
(4) module parameters (optional ).
A module parameter is the value that can be passed to a module when it is loaded. It corresponds to the global variable in the module.
(5) module export symbol (optional ).
The kernel module can export symbols (symbol, corresponding to functions or variables), so that other modules can use the variables or functions in this module.
(6) module author and other information declarations (optional ).

The module Loading Function Linux kernel module loading function is generally declared as _ init. The typical module loading function is shown in code list 4.2.
Code List 4.2 kernel module loading Functions
1 static int _ init initialization_function (void) 2 {3/* initialization Code */4} 5 module_init (initialization_function );

The module-loaded function is specified in the form of module_init (function name. It returns an integer value. If Initialization is successful, 0 is returned. When initialization fails, the error code should be returned. In the linux kernel, the error code is a negative value close to 0. It is defined in <linux/errno. h> and contains symbol values such as-ENODEV and-ENOMEM. It is a good habit to always return the corresponding error code, because only in this way can the user program convert them into meaningful error message strings using methods such as perror.
In the Linux kernel, you can use request_module (const char * fmt ,...) Function to load the kernel module. Driver developers can call
Request_module (module_name );
This flexible method is used to load other kernel modules.
In Linux, if all functions labeled as _ init are directly compiled into the kernel and become part of the kernel image, they are stored in the. init. text section during connection.
# Define _ init _ attribute _ (_ section _ (". init. text ")))
All the _ init functions are in the Section. initcall. init also saves a function pointer. during initialization, the kernel will call these _ init functions through these function pointers and release the init section (including. init. text ,. initcall. init.
In addition to functions, data can also be defined as _ initdata. For data only required during initialization, the kernel can release the memory they occupy after initialization. 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_data);    return 0;}module_init(hello_init);static void __exit hello_exit(void){    printk(KERN_INFO "Goodbye, world\n");}module_exit(hello_exit);

Module unmount Function
The Linux kernel module load function is generally declared as a _ exit identifier. The typical form of the module unload function is shown in code list 4.3.
Code List 4.3 kernel module uninstall Function
1 static void _ exit cleanup_function (void) 2 {3/* release code */4} 5 module_exit (cleanup_function );

The module uninstallation function is executed when the module is detached. No value is returned. It must be specified in the form of module_exit (function name. In general, the module unmount function must implement the opposite function of the module load function.
We use _ exit to modify the module uninstallation function. We can tell the kernel that if the relevant module is directly compiled into the kernel (that is, built-in), cleanup_function () the function is omitted and is not directly connected to the final image. Since the module has been built-in, it is impossible to uninstall it, and there is no need to uninstall the function. In addition to functions, the data used in the exit phase can also be described as _ exitdata.

Module Parameters
We can use "module_param (parameter name, parameter type, parameter read/write permission)" to define a parameter for the module, for example, the following code defines one integer parameter and one character pointer parameter:
static char *book_name = "dissecting Linux Device Driver";module_param(book_name, charp, S_IRUGO);static int book_num = 4000;module_param(book_num, int, S_IRUGO);

When loading the kernel module, you can pass parameters to the module, in the form of "insmode (or modprobe) Module name parameter = parameter value". If not, the parameter uses the default value defined in the module. If the module is built-in, it cannot be insmod, but bootloader can set the module name in bootargs. parameter Name = value "to pass parameters to the built-in module.
The parameter types can be byte, short, ushort, int, uint, long, ulong, charp (character pointer), bool, or invbool (Boolean inverse ), when the module is compiled, the types declared in module_param are compared with the types defined in the variables to determine whether they are consistent.
In addition, the module can also have an array of parameters in the form of "module_param_array (array name, array type, group leader, parameter read/write permission )".
After the module is loaded, the directory named after this module appears under the/sys/module/directory. When "read/write permission" is set to 0, this parameter indicates that the file node corresponding to the sysfs file system does not exist, if the command line parameter "parameter read/write permission" of this module is not 0, the parameters directory will also appear under the directory of this module, containing a series of file nodes named after the parameter name, the permission value of these files is the "parameter read/write permission" that is passed into module_param (), and the content of the file is the parameter value.
When running the insmod or modprobe command, use commas to separate the input array elements.
Now we define a module that contains two parameters (for example, code list 4.4, which is located in the source code/kernel/drivers/param directory of this book ), observe the output when the module is loaded and when the parameters are not passed.
Code List 4.4 kernel modules with Parameters
01 #include <linux/init.h>02 #include <linux/module.h>0304 static char *book_name = "dissecting Linux Device Driver";05 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)11 {12     printk(KERN_INFO "book name:%s\n", book_name);13     printk(KERN_INFO "book num:%d\n", book_num);14     return 0;15 }16 module_init(book_init);1718 static void __exit book_exit(void)19 {20     printk(KERN_INFO "book module exit\n ");21 }22 module_exit(book_exit);2324 MODULE_AUTHOR("Barry Song <baohua@kernel.org>");25 MODULE_LICENSE("GPL v2");26 MODULE_DESCRIPTION("A simple Module for testing module params");27 MODULE_VERSION("V1.0");

Run the "insmod book. ko" command to load the above modules. The corresponding output is the default value in the module. view the "/var/log/messages" log file to view the kernel output:
# tail -n 2 /var/log/messagesJul  2 01:03:10 localhost kernel:  <6> book name:dissecting Linux Device DriverJul  2 01:03:10 localhost kernel:  book num:4000

When you run the "insmod book. ko book_name = 'goodbook' book_num = 5000" command, the output is the user-passed parameter:
# tail -n 2 /var/log/messagesJul  2 01:06:21 localhost kernel:  <6> book name:GoodBookJul  2 01:06:21 localhost kernel:  book num:5000Jul  2 01:06:21 localhost kernel:  book num:5000
In addition, you can see the parameters of the book module in the/sys directory:
barry@barry-VirtualBox:/sys/module/book/parameters$ tree.├── book_name└── book_num
The exported Linux "/proc/kallsyms" file corresponds to the kernel symbol table, which records the memory address of the symbol and symbol.
The module can use the following macro export symbol to the kernel symbol table:
EXPORT_SYMBOL (symbol name );
EXPORT_SYMBOL_GPL (symbol name );
The exported symbols can be used by other modules. Just declare them before using them. EXPORT_SYMBOL_GPL () is only applicable to modules that contain GPL permission. Code List 4.5 provides an example of the kernel module that exports integer addition and subtraction function symbols.
Code List 4.5 symbol export in the kernel module
01 #include <linux/init.h>02 #include <linux/module.h>0304 int add_integar(int a, int b)05 {06     return a + b;07 }08 EXPORT_SYMBOL_GPL(add_integar);0910 int sub_integar(int a, int b)11 {12     return a - b;13 }14 EXPORT_SYMBOL_GPL(sub_integar);1516 MODULE_LICENSE("GPL v2");

Find add_integar and sub_integar information 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 description
In the Linux kernel module, we can use MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_VERSION, MODULE_DEVICE_TABLE, and MODULE_ALIAS to declare the author, description, version, device table, and alias of the module, for example:
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 usually created to indicate the devices supported by the driver module, as shown in code list 4.6.
Code List 4.6 list of devices supported by the driver
1/* Device table corresponding to this driver */2 static struct usb_device_id skel_table [] = {3 {USB_DEVICE (USB_SKEL_VENDOR_ID, 4 USB_SKEL_PRODUCT_ID )}, 5 {}/* Table end */6}; 78 MODULE_DEVICE_TABLE (usb, skel_table );

In this case, you do not need to understand the role of MODULE_DEVICE_TABLE. The relevant sections will be described in detail later.
Module usage count
In the Linux 2.4 kernel, the module uses the MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros to manage its own counts.
In Linux 2.6 and later, the kernel provides the module count management interfaces try_module_get (& module) and module_put (& module) to replace the modules in Linux 2.4 kernel with the count management macro. Generally, the module does not need to manage the module count, and the module count management also takes into account the impact of SMP and PREEMPT mechanisms.

Int try_module_get (struct module * module );

This function is used to increase the module usage count. If the return value is 0, the call fails. The expected module is not loaded or is being detached.

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 () are closely related to the device models in Linux 2.6 kernel. After Linux 2.6, the kernel defines the struct module * owner domain for different types of devices to point to the module that manages the device. When you start to use a device, the kernel uses try_module_get (dev-> owner) to increase the use count of the owner module managing the device. When you no longer use the device, the kernel uses module_put (dev-> owner) to reduce the use count of the owner module managing this device. In this way, when a device is in use, the module that manages the device cannot be detached. The module can be detached only when the device is no longer in use.
In Linux 2.6 and later kernels, device drivers rarely need to call try_module_get () and module_put () in person (), the driver written by the developer is usually the owner module that supports a specific device, the counting manager of the device owner module simplifies device driver development by implementing more underlying code in the kernel, such as bus drivers or core modules shared by such devices.


Module Compilation

We can compile a simple Makefile for the template in code list 4.1:

KVERS = $(shell uname -r)# Kernel modulesobj-m += hello.o# Specify flags for the module compilation.#EXTRA_CFLAGS=-g -O0build: kernel_moduleskernel_modules:      make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modulesclean:      make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

The Makefile should be in the same directory as the source code hello. c. Enable EXTRA_CFLAGS =-g-O0 to obtain the hello. ko module containing debugging information. The module obtained by running the make command can be run directly on the PC.
If a module contains multiple. c files (such as file1.c and file2.c), you should write Makefile as follows:
Obj-m: = modulename. o
Modulename-objs: = file1.o file2.o

The module and the GPLLinux kernel have two ways to export symbols to the module. One is EXPORT_SYMBOL () and the other is EXPORT_SYMBOL_GPL (). This is consistent with the export symbol of module a to module B.
The Documentation/DocBook/kernel-hacking.tmpl of the kernel clearly states that "the symbols exported by EXPORT_SYMBOL_GPL () can only be seen by modules with a MODULE_LICENSE () that specifies a GPL compatible license. it can be seen that the symbols exported by the kernel using EXPORT_SYMBOL_GPL () cannot be referenced by non-GPL modules.
Because a considerable number of kernel symbols are exported using EXPORT_SYMBOL_GPL (), some companies have historically changed the EXPORT_SYMBOL_GPL () of the kernel to EXPORT_SYMBOL (), then, the modified kernel is published as GPL. After the kernel is modified, the module no longer uses the kernel's EXPORT_SYMBOL_GPL () symbol, so the module no longer needs GPL. The response 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 wowould almost immediately fall under the" willful infringement "thing, and that it wocould make it MUCH easier to get triple damages and/or injunctions, since they clearly knew about it ". Therefore, this practice may constitute "willful infringement )".
Another method is to write a wrapper kernel module (which complies with GPL), encapsulate the symbols exported from EXPORT_SYMBOL_GPL () and export them again in the form of EXPORT_SYMBOL, other modules call the wrapper function instead of directly calling the kernel, as shown in Figure 4.1. This approach is also controversial.
 
Figure 4.1 Export EXPORT_SYMBOL_GPL again with EXPORT_SYMBOL
It is generally considered that the Linux kernel does not use non-GPL permission.


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.