Article Title: describes the compatibility of device drivers in Linux. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
Latest Progress
Linux has been developing rapidly, and developers are always eager to improve the core. They do not consider backward compatibility. This free development leads to a certain degree of incompatibility between the device driver interfaces provided by different versions of the core. However, it remains compatible at the application level. In addition to applications that require low-level interaction with core features (such as ps ).
On the other hand, the device driver is directly linked to the core image, so it must be consistent with the changes to the data structure, global variables, and functions derived from the internal system. In the development process, new features are modified internally as they are added; new implementations Replace the implementations because practices prove that they are faster and clearer. Although incompatibility requires programmers to do some extra work when writing modules, I think continuous development is the success point of the Linux community: strict sequential compatibility eventually proves harmful.
This chapter describes the differences between 2.0.x and 2.1.43, which will be similar to the upcoming release of 2.2. Linus introduced the most important changes in earlier versions 2.1, so that the core can go through several more versions 2.1, so that the driver author has enough time to stabilize the driver before the development is locked to publish a stable 2.2 release. The following section describes how the driver processes the differences between 2.0 and 2.1.43. I have modified all the Sample Code introduced in this book so that they can be compiled and run on both 2.0 and 2.1.43, and most versions between them. The new driver version can be obtained from the v2.1 directory of the online example on the FTP site of o'reilly. The compatibility between 2.0 and 2.1 is obtained through the header file sysdep-2.1.h and it can be integrated with your own modules. I chose not to extend compatibility to 1.2 to avoid loading too many conditions for C code, and the differences between 1.2 and 2.0 have already been explained in the previous chapter. When I was about to write this book, I learned that some small incompatibility was introduced from 2.1.43; I am not going to comment on it, because I cannot guarantee full support for these latest versions.
Note that in this chapter, I will not describe all the new things introduced in the 2.1 Development Series. All I have to do is port the 2.0 module so that it can run on the 2.0 and 2.1 cores. Using 2.1 of features means giving up support for 2.0 releases that do not have these features. Version 2.0 is still the focus of this book. When writing a sysdep-2.1.h, I have tried to familiarize you with the new API, And the macros I introduced are used to make 2.1 of the code run on 2.0 instead of the opposite.
This chapter introduces incompatibility in a descending order of importance. The most important differences are introduced first, and the secondary details are described later.
Modular
In the Linux community, modularization becomes more and more important. Developers decide to replace the old one with a clearer implementation. Header file It was completely rewritten in 2.1.18, and a new API was introduced. As you expected, new implementations are easier to use than old ones. To load your module, you will need to pack the modutils-2.1.34 or even update the version (for details, see Documentation/
Changes ). When used with the old core, this package can return to the compatibility mode, so you can replace modules-2.0.0 with this new package, even if you often switch between 2.0 and 2.1.
Lead symbol
The new interface of the symbol table is much easier than the previous one. It depends on the following macro:
EXPORT_NO_SYMBOLS; this macro is equivalent to register_symtab (NULL); it can appear inside or outside a function, because it only guides the assembler without generating actual code. If you want to compile the module on Linux2.0, this macro should be used in init_module.
EXPORT_SYMTAB; if you want to introduce some symbols, the module must contain Previously, this macro was defined.
EXPORT_SYMBOL (name); this macro indicates that you want to introduce this symbol name. It must be used outside of any function.
EXPORT_SYMBOL_NOVERS (name) uses this macro instead of EXPORT_SYMBOL () to forcibly discard version information, even if the Code with version support is compiled. This is useful for avoiding unnecessary re-compilation. For example, the memset function will always work in the same way; The introduction symbol without the version information allows developers to change the implementation (or even use the data type) without the insmod mark incompatibility. This macro is unlikely to be needed in modular code.
If none of these macros are used in your source code, all non-static symbols are extracted. This is the same as in 2.0 if none of these macros are used in your source code, all non-static symbols are extracted; this is the same as in 2.0. If this module is generated from several source files, you can extract symbols from any source files and share any symbols within the scope of the module. As you can see, the new method for extracting symbol tables solves some problems, but this innovation also introduces an important incompatibility: a module that introduces some symbols, if you want to compile and run on both 2.0 and 2.1, you must use Conditional compilation to include two implementations. The following is the export module (v2.1/misc-modules/export. c) how to deal with this problem when 2.1.18 or the updated Core is used, why is the REGISTER_SYMTAB extension not done, because there is nothing to do in init_module; EXPORT_SYMBOL must be used outside the function to extract the unique module symbol.
The new implementation of the core module utilizes the features of the ELF binary format for better flexibility. More specifically, new implementations of the core module utilize the features of the ELF binary format for better flexibility. More specifically, when constructing an ELF target file, you can declare Sections other than "body", "data", and "bss. A "section" is a continuous data area, similar to the concept of "segment.
For 2.1, the core module must be compiled in the ELF binary format. In fact, the 2.1 core uses the ELF section (see "handling core space errors") and can only be compiled into ELF. Therefore, the limitation of the module is not a real limitation. Use ELF to allow information domains to be stored in the target file. Curious readers can use objdump? Section-headers is used to observe the node header, and objdump is used? Section =. modinfo? Full-contents to view specific module information. In fact, the. modinfo section is used to store module information. It contains the value called "parameter" and can be modified during loading.
When compiling on 2.1, a parameter can be declared as MODULE_Parm (variable, type-description) using a macro, as shown in the following figure. When you use this macro in the source file, the compiler is notified to insert a description string in the target file. This description indicates that variable is a parameter and its type corresponds to type-description. Insmod and modprobe check the target file to ensure that you are allowed to modify variable and check the actual type of parameters. Type check is very important to prevent unpleasant errors. For example, a string overwrites an integer, or an error treats a long integer as a short integer. In my opinion, I will provide several lines of sample code for the best macro method. The following code is an imaginary Nic type-description string in the header file And it can be found in the entire core source code for your convenience. It is worth noting that the trick is to parameterize the length of an array, like the above io. For example, suppose that the number of peripheral boards supported by the network driver is represented by a macro MAX_DEVICES, rather than a hard-written number 4. For this purpose, the header file Defines a macro (_ MODULE_STRING), which uses the C Preprocessor to "stringize" A Macro ". This macro can be used as follows:
int io[MAX_DEVICES+1]={0,}; MODULE_Parm(io, “1-” __MODULE_STRING(MAX_DEVICES) “i”);
|
In the previous line, the value "stringized" is connected together with other strings to form a meaningful string in the target file. The scull sample module also uses MODULE_PARM to declare its parameters (scull_major and other integer variables ). This problem may occur during compilation on Linux2.0, where the macro is not defined. The simple fix I chose is to define MODULE_Parm IN THE sysdep-2.1.h, so that it expands to a null statement when compiled with the 2.0 header file. Other meaningful values can exist in the module. modinfo section like MODULE_AUTHOR (), but they are not currently used. See For more information.
/Proc/modules
The format of/proc/modules is slightly changed in 2.1.18, and all modular code is rewritten. Although this change does not affect the source code, you may not be interested in its details, because/proc/modules is often checked during module development.
The new format is Row-oriented like the old one. Each line contains the following fields:
Module name: this domain is the same as Linux2.0.
Large Module: small. This is a decimal number. The report length is measured in bytes (instead of memory pages. If the module does not use the count, the count report is-1. This is a new feature introduced together with the new modular code; you can write a module, and its removal can have a function control instead of using the count. This function determines whether the module can be detached. For example, the ipv6 module uses this feature.
[1] [2] [3] [4] [5] Next page