Makefile Analysis of Linux driver module "Go"

Source: Internet
Author: User

This article was reproduced from: http://blog.chinaunix.net/uid-29307109-id-3993784.html

1. Get Kernel version

When a device driver needs to support different versions of the kernel at the same time, during the compile phase, the kernel module needs to know the version of the kernel source currently in use, thereby using the appropriate kernel API. Under 2.4 and 2.6 cores, the source dock file Linux/version.h is defined as:

Linux_version_code― kernel version of the binary representation, master, slave, revision number corresponding to one byte;

Kernel_version (Major, minor, release)-The binary version number is constructed by the master, slave, revision number.

In a device driver that supports both the 2.4 and 2.6 cores, you can often see the following code snippet:


Listing 1: Determine the code snippet for the kernel version.

Back to top of page

2. Changes in kernel module mechanisms

2.1 Module Compilation

From 2.4 to 2.6, the compilation of external loadable kernel modules, the connection process, and the writing of makefile have changed.

2.4 Kernel, the module compiles only the kernel source dock file, need to define module before including Linux/modules.h, the kernel module suffix that is generated after compiling and connecting is. O.

2.6 Kernel, the module's compilation needs to be configured the kernel source code; The kernel module suffix generated after compiling and connecting is. Ko; the compilation process starts with the kernel source directory, reads the top-level makefile file, and then returns the directory where the module source code resides.


Listing 2:2.4 makefile templates for kernel modules

#Makefile2.4kver=$ (Shell uname-r) kdir=/lib/modules/$ (kver)/buildobjs=mymodule.ocflags=-d__kernel__-I$ (KDIR)/ Include-dmodule     -d__kernel_syscalls__-dexport_symtab  -o2-fomit-frame-pointer  -wall  - Dmodversions           -include $ (kdir)/include/linux/modversions.hall: $ (OBJS) mymodule.o:file1.o file2.old-r-o [email Protected] $^clean:rm-f *.O

In the 2.4 kernel, the kernel module's makefile and the normal user program's makefile are both structurally and syntactically identical, but the-d__kernel__-dmodule must be defined in Cflags, specifying the kernel header file directory-i$ (kdir)/include. It is important to note that variables are defined in the cflags, not in the module source file, on the one hand these predefined variables can be visible to all source files in the module, on the other hand is equivalent to defining these predefined variables in the source file starting position. In module compilation, for these global predefined variables, it is generally defined in cflags.


Listing 3:2.6 makefile templates for kernel modules

# MAKEFILE2.6IFNEQ ($ (kernelrelease),) #kbuild syntax. Dependency Relationshsip of files and target modules is listed HERE.MYMODULE-OBJS: = file1.o file2.oobj-m: = MYMODULE.O E Lsepwd  : = $ (shell pwd) kver? = $ (Shell uname-r) Kdir: =/lib/modules/$ (kver)/buildall:$ (make)-C $ (kdir) m=$ (pwd) clean : Rm-rf. *.cmd *.o *.mod.c *.ko. tmp_versionsendif

Kernelrelease is a variable defined in the top-level makefile of the kernel source, and kernelrelease is not defined when the first read executes this makefile, so make reads the content after the else is executed. If the goal of make is clean, perform the clean operation directly and then end. When the target of make is all, the-C $ (kdir) indicates that jumping to the kernel source directory reads the makefile;m=$ (PWD) there and then returns to the current directory to continue to read in and execute the current makefile. When returned from the kernel source directory, Kernelrelease has been defined and Kbuild is also initiated to parse the Kbuild syntax, and make will continue to read the content before else. Else before is a Kbuild syntax statement that indicates the dependencies of the files in the module's source code and the name of the target module to be generated. MYMODULE-OBJS: = FILE1.O FILE2.O indicates that MYMOUDULE.O is generated by FILE1.O and FILE2.O connections. Obj-m: = MYMODULE.O indicates that the MYMODULE.O module will be generated after the connection is compiled.

To add, "$ (make)-C $ (kdir) m=$ (pwd)" and "$ (make)-C $ (kdir) Subdirs =$ (PWD)" function is equivalent, the latter is the older method of use. It is recommended to use m instead of Subdirs, the former is more explicit.

From the above comparison, it can be seen from the makefile, in the 2.6 kernel, kernel module compilation does not have to define complex cflags, and the module of the file dependencies of the expression concise and clear.


Listing 4: Makefile that can operate at both 2.4 and 2.6 cores

#makefile for 2.4 & 2.6vers26=$ (findstring 2.6,$ (Shell uname-r)) makedir?=$ (shell pwd) ifeq ($ (VERS26), 2.6) include $ ( MakeDir)/makefile2.6elseinclude $ (makedir)/makefile2.4endif  

2.2 Version checking when the module is loaded

The Linux kernel has been updated and perfected, and the modules compiled under version a kernel are usually not run under the B version kernel, so there must be a mechanism to restrict the modules generated under the version a kernel to be loaded under the version B kernel.

The 2.4 and 2.6 cores have undergone a fundamental change in the version checking mechanism of loadable kernel modules, but these changes are largely transparent to device-driven developers. In order for the version check mechanism to take effect when the module is loaded, the 2.4 kernel simply needs to be defined in the Cflags

2.6 Cores, developers do not need to take any action.

However, it is still necessary to clarify the version checking mechanism of the 2.4 and 2.6 cores for loadable modules.

2.4 Kernel, execute ' cat/proc/ksyms ' to see the kernel symbol followed by a string of check strings, this check string is related to the kernel version. There are many *.ver files in the kernel source dock file Linux/modules directory that serve as a check suffix for kernel symbols, such as a row in the Ksyms.ver file #define PRINTK _set_ver (PRINTK). The Linux/modversions.h file will contain all the ver files. So when the module contains the Linux/modversions.h file, at compile time, the kernel symbol used in the module is essentially a kernel symbol with a checksum suffix. "Invalid module Format" error occurs when the module is loaded, if the checksum string of the kernel symbol used in the module is inconsistent with the checksum string of the corresponding kernel symbol exported by the current running kernel, that is, the kernel symbol used by the module does not exist in the current kernel space.

Adding a check string to the kernel symbol to verify that the version of the module matches the kernel version is cumbersome and wasteful of kernel space, and with SMP (symmetric multiprocessor), PREEMPT (preemptive Kernel), such as the introduction and refinement of the 2.6 kernel, the module runtime depends not only on the kernel version, but also on the configuration of the kernel, when the kernel symbol check code consistency can not be a judge module can be loaded sufficient conditions. In the 2.6 kernel, the vermagic_string,vermagic_string defined in Linux/vermagic.h contains not only the kernel version number, but also the configuration information such as the GCC version used by the kernel, SMP and preempt. When the module is compiled, we can see that "Modpost" is displayed on the screen. At this stage, Vermagic_string is added to the Modinfo segment of the module. You can see the code in the module's subsequent processing section in the scripts\mod\modpost.c file under the kernel source directory. After the module is compiled, the ' modinfo Mymodule.ko ' command allows you to view information such as the vermagic of this module. The module loader in the 2.6 kernel holds the kernel version information, and when the module is loaded, the loader compares the saved kernel vermagic with the vermagic information stored in the Modinfo section of the module to be loaded when they are identical. For example, Fedora Core 4 and Core 2 are using the 2.6 kernel, the invalid module format error will appear when Fedore Core 2 loads the Hello.ko generated under Fedora Core4.

#insmod hello.koinvalid module Format hello:version Magic ' 2.6.11-1.1369_fc4 686 regparm 4KSTACKS gcc-4.0 ' should be ' 2.6 .5-1.358 686 Regparm 4KSTACKS gcc-3.3 '

2.3 Initialization and exit of the module

In the 2.6 kernel, the kernel module must call the macro Module_init and Module_exit () to register the initialization and exit functions. In the 2.4 kernel, if the initialization function is named Init_module (), the Exit function is named Cleanup_module (), you do not have to use Module_init with the MODULE_EXIT macro. It is recommended to use Module_init and Module_exit macros to make the code work in both the 2.4 and 2.6 cores.


Listing 5: Initialization and exit templates for modules with 2.4 and 2.6 cores

#include   /* Needed by all modules *     /#include/* Needed for Init&exit macros */static int mod_init_func (void) {/ *code Here*/return 0;} static void Mod_exit_func (void) {/*code here*/}module_init (mod_init_func); Module_exit (Mod_exit_func);

It is important to note that initialization and exit functions must be defined before macro module_init and module_exit are used, or a compilation error will occur.

2.4 Module Usage Count

The module is not allowed to be unloaded when it is used. In the 2.4 kernel, the module itself manages the counts that it uses by Mod_inc_use_count, Mod_dec_use_count macros. The 2.6 kernel provides a more robust and flexible module count Management interface Try_module_get (&module) and Module_put (&module) Replace the module in 2.4 with the Count management macro, the usage count of the module does not have to be managed by itself, and the effects of the SMP and preempt mechanisms are taken into account when the management module uses the count.

int try_module_get (struct module *module): Used to increase the module usage count; If returned to 0, the call fails, the module you want to use is not loaded or is being unloaded.

void Module_put (struct module *module): Reduces module usage count.

The introduction and use of Try_module_get and Module_put is closely related to the device model under the 2.6 kernel. The module is used to manage hardware devices, and the 2.6 kernel defines a struct module *owner domain for different types of devices to point to the module that manages this device. such as the definition of a character device:

struct Cdev {struct Kobject kobj;struct module *owner;struct file_operations *ops;struct list_head list;dev_t Dev;unsigne d int count;};

From the point of view of device usage, use Try_module_get (Dev->owner) to increase the usage count of the owner module that manages this device when you need to open and start using a device, and use module_put when you turn off and no longer use this device (dev- >owner) reduces the usage count for the owner module that manages this device. This way, when the device is in use, the module that manages the device cannot be uninstalled, and the module can be uninstalled only if the device is no longer in use.

2.6 Cores, for developers who write drivers for specific devices, there is basically no need to use Try_module_get and module_put, because the driver written by the developer is typically the owner module that supports a specific device. The count management of the owner module for this device is implemented by the more underlying code in the kernel, such as a bus driver or a core module shared by such devices, simplifying device-driven development.

Back to top of page

2.5 kernel symbols for module output

2.4 Cores, by default, non-static global variables and functions in the module are output to kernel space after the module is loaded.

2.6 Kernel, by default, the non-static global variables and functions in the module will not be output to kernel space after the module is loaded, you need to explicitly call the macro export_symbol to output. Therefore, under the module of the 2.6 kernel, the call of the Export_no_symbols macro is meaningless and is an empty operation. In a device driver that supports both 2.4 and 2.6 cores, the kernel symbols of the module can be output through the following code snippet


Listing 6: Support for both 2.4 and 2.6 output kernel symbol code snippet

#include #ifndef linux26export_no_symbols; #endifEXPORT_SYMBOL (VAR); Export_symbol (func);

It is important to note that if you need to use Export_symbol under the 2.4 kernel, you must define Export_symtab in the Cflags, otherwise the compilation will fail.

From a good code-style point of view, the module does not need to output to the kernel space and not need to be used for other files in the module global variables and functions are best explicitly declared as static type, the kernel symbol that needs to be output is prefixed with the module name.

After the module is loaded, the kernel symbols of the module output can be viewed via/proc/kallsyms under the/proc/ksyms, 2.6 cores under the 2.4 core.

Back to top of page

2.6 command Line input parameters for the module

When loading kernel modules, the user can pass some parameters to the module, such as ' Modprobe modname var=value ', otherwise var will use the default values defined in the module.

Under 2.4 kernels, Macro module_parm (var,type) defined in Linux/module.h is used to pass command-line arguments to the module. var is the variable name that accepts the parameter value, and the type is a string [min[-max]]{b,h,i,l,s} that takes the following format. Min and Max are used to represent the range of array elements that are allowed to be entered when the parameter is an array type; b:byte;h:short;i:int;l:long;s:string.

Under 2.6 kernels, Macro module_parm (Var,type) is no longer supported. The following macros are defined in the header file linux/moduleparam.h:

Module_param (name, type, perm) Module_param_array (name, type, Nump, perm)

Type types can be byte, short, ushort, int, uint, long, ulong, CHARP, BOOL or Invbool, No longer takes the form of a string in the 2.4 kernel, and when the module compiles, the type declared here is compared to the types defined by the variable to determine whether it is consistent.

Perm represents the properties of the file node that this parameter corresponds to in the Sysfs file system. The 2.6 kernel uses the Sysfs file system, which is a more powerful file system built in memory than Proc. SYSFS file system can be dynamic, real-time, organized to reflect the current system of hardware, driver and other state. When Perm is 0 o'clock, this parameter does not exist for the corresponding file node under the Sysfs file system. After the module is loaded, a directory named after the module name will appear in the/sys/module/directory. If this module has a command-line argument that does not have a perm of 0, the parameters directory will appear under the directory of this module, containing a series of file nodes named after the parameter name, which have a permission value equal to perm and the contents of the file as the value of the parameter.

Nump is a pointer to a variable that holds the number of input array elements. You can set NULL when you do not need to save the number of array elements that are actually entered. From 2.6.0 to 2.6.10, the variable name must be assigned to Nump; starting with the 2.6.10 version, you should assign a reference to the variable to Nump, which is easier for developers to understand. When you load a module, separate the input array elements with commas.


Listing 7: module input parameter template for 2.4 and 2.6 cores

#include #ifdef linux26#include #endif int debug = 0;char *mode = "800x600"; int tuner[4] = {1, 1, 1, 1}; #ifdef Linux26int Tuner_c = 1;  #endif #ifdef linux26module_parm (Debug, "I"); Module_parm (Mode, "s"); Module_parm (tuner, "1-4i"); #elsemodule_param (debug, int, 0644); Module_param (mode, Charp, 0644); #if linux_version_ CODE >= kernel_version (2, 6, Ten) Module_param_array (tuner, int, &tuner_c, 0644); #elsemodule_param_array (tuner, int, tuner_c, 0644); #endif #endif

After the module is compiled, the module can be loaded with the following input: ' modprobe my_module mode=1024x768 debug=1 tuner=22,33 '.

The linux/moduleparam.h also defines:

Module_param_array_named (name, array, type, Nump, perm) Module_param_call (name, set, GET, ARG, perm) module_param_named ( Name, value, type, perm)

Readers can refer to linux/moduleparam.h to see a detailed description of these macros, one thing to note, in the 2.6 kernel, Module_param this series of macros use lowercase names.

2.7 License Statement for the module

Starting with the 2.4.10 kernel, the module must declare a license for this module through the Module_license macro, otherwise when the module is loaded, it will receive a warning that the kernel is contaminated with "kernel tainted". As can be seen from the Linux/module.h file, the meaningful licenses accepted by the kernel are "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", "Dual MPL/GPL", " Proprietary ".

In a device driver that supports both the 2.4 and 2.6 cores, the module can declare its own license as follows.


Listing 8: module License Declaration template for 2.4 and 2.6 cores

#if linux_version_code >= kernel_version (2,4,10) module_license ("GPL"); #endif

2.8 Summary

In addition, there are some changes in the module mechanism in the 2.6 kernel that are not often used by driver developers. such as the interface for loading kernel modules Request_module is request_module (const char * module_name) under 2.4, and Request_module (const char *FMT, ...) under the 2.6 kernel. Under the 2.6 kernel, driver developers can invoke the

Request_module ("msp3400"); Request_module ("char-major-%d-%d", Major (Dev), MINOR (Dev));

This is a more flexible way to load other kernel modules.

2.6 The kernel also provides a module_alias (ALIAS) macro in Linux/module.h, which can be used to define one or more nicknames for itself by calling this macro. Under the 2.4 kernel, the user can only define a nickname for the module in/etc/modules.conf.

From the above comparison, we can see that from 2.4 to 2.6 cores, the changes in the management mechanism of the Loadable modules make device-driven development more concise, flexible and robust.

Resources

Porting device drivers to the 2.6 kernel

Makefile Analysis of Linux driver module "Go"

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.