Version Dependency

Bear in mind that your module's code has to be recompiled for each version of the kernel that it is linked to—at least, in the absence of modversions, not covered here as they are more for distribution makers than developers. Modules are strongly tied to the data structures and function prototypes defined in a particular kernel version; the interface seen by a module can change significantly from one kernel version to the next. This is especially true of development kernels, of course. 请记住,您的模块代码必须针对它链接到的每个内核版本重新编译——至少,在没有 modversions 的情况下,这里没有介绍,因为它们更多地是为分发制造商而不是开发人员提供的。 模块与特定内核版本中定义的数据结构和函数原型紧密相关; 模块看到的接口可以从一个内核版本到下一个内核版本发生显着变化。 当然,开发内核尤其如此。

The kernel does not just assume that a given module has been built against the proper kernel version. One of the steps in the build process is to link your module against a file (called vermagic.o) from the current kernel tree; this object contains a fair amount of information about the kernel the module was built for, including the target kernel version, compiler version, and the settings of a number of important configuration variables. When an attempt is made to load a module, this information can be tested for compatibility with the running kernel. If things don't match, the module is not loaded; instead, you see something like: 内核不仅仅假设给定的模块是针对正确的内核版本构建的。 构建过程中的步骤之一是将模块链接到当前内核树中的文件(称为 vermagic.o); 该对象包含大量有关构建模块的内核的信息,包括目标内核版本、编译器版本以及许多重要配置变量的设置。 当尝试加载模块时,可以测试此信息与正在运行的内核的兼容性。 如果不匹配,则不加载模块; 相反,您会看到如下内容:

# insmod hello.ko

Error inserting './hello.ko': -1 Invalid module format

A look in the system log file (/var/log/messages or whatever your system is configured to use) will reveal the specific problem that caused the module to fail to load. 查看系统日志文件(/var/log/messages 或您的系统配置使用的任何内容)将揭示导致模块无法加载的具体原因。

If you need to compile a module for a specific kernel version, you will need to use the build system and source tree for that particular version. A simple change to the KERNELDIR variable in the example makefile shown previously does the trick. 如果您需要为特定内核版本编译模块,则需要使用该特定版本的构建系统和源代码树。 对前面显示的示例 makefile 中的 KERNELDIR 变量进行简单更改就可以解决问题。

Kernel interfaces often change between releases. If you are writing a module that is intended to work with multiple versions of the kernel (especially if it must work across major releases), you likely have to make use of macros and #ifdef constructs to make your code build properly. This edition of this book only concerns itself with one major version of the kernel, so you do not often see version tests in our example code. But the need for them does occasionally arise. In such cases, you want to make use of the definitions found in linux/version.h. This header file, automatically included by linux/module.h, defines the following macros: 内核接口经常在不同版本之间改变。 如果您正在编写一个旨在与多个内核版本一起使用的模块(特别是如果它必须跨主要版本工作),您可能必须使用宏和#ifdef 构造来使您的代码正确构建。 这本书的这个版本只关注内核的一个主要版本,所以你不会经常在我们的示例代码中看到版本测试。 但是偶尔会出现对它们的需求。 在这种情况下,您需要使用 linux/version.h 中的定义。 这个头文件,由 linux/module.h 自动包含,定义了以下宏:

UTS_RELEASE

This macro expands to a string describing the version of this kernel tree. For example, "2.6.10".此宏扩展为描述此内核树版本的字符串。 例如,“2.6.10”。

LINUX_VERSION_CODE

This macro expands to the binary representation of the kernel version, one byte for each part of the version release number. For example, the code for 2.6.10 is 132618 (i.e., 0x02060a).[2] With this information, you can (almost) easily determine what version of the kernel you are dealing with. 该宏扩展为内核版本的二进制表示,版本发布号的每一部分一个字节。 例如,2.6.10 的代码是 132618(即 0x02060a)。 [2] 有了这些信息,您(几乎)可以轻松地确定您正在处理的内核版本。

KERNEL_VERSION(major,minor,release)

This is the macro used to build an integer version code from the individual numbers that build up a version number. For example, KERNEL_VERSION(2,6,10) expands to 132618. This macro is very useful when you need to compare the current version and a known checkpoint. 这是用于从构建版本号的各个数字构建整数版本代码的宏。 例如,KERNEL_VERSION(2,6,10) 扩展为 132618。当您需要比较当前版本和已知检查点时,此宏非常有用。

Most dependencies based on the kernel version can be worked around with preprocessor conditionals by exploiting KERNEL_VERSION and LINUX_VERSION_CODE. Version dependency should, however, not clutter driver code with hairy #ifdef conditionals; the best way to deal with incompatibilities is by confining them to a specific header file. As a general rule, code which is explicitly version (or platform) dependent should be hidden behind a low-level macro or function. High-level code can then just call those functions without concern for the low-level details. Code written in this way tends to be easier to read and more robust. 通过利用 KERNEL_VERSION 和 LINUX_VERSION_CODE,可以使用预处理器条件来解决大多数基于内核版本的依赖关系。 但是,版本依赖不应使驱动程序代码与毛茸茸的#ifdef 条件混为一谈; 处理不兼容性的最佳方法是将它们限制在特定的头文件中。 作为一般规则,明确依赖于版本(或平台)的代码应该隐藏在低级宏或函数后面。 然后,高级代码可以只调用这些函数而无需关心低级细节。 以这种方式编写的代码往往更易于阅读且更健壮。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mounter625

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值