如何构建 Linux 内核模块以使其与所有内核版本兼容?

问题描述 投票:0回答:3

我想构建一个与所有内核版本兼容的内核模块。 例如,如果我在内核 3.2.0-29 上构建内核模块并尝试在 3.2.0-86 上加载它,则会收到以下错误:

modprobe my_driver

致命:插入 my_driver 时出错(/lib/modules/3.2.0-86-generic/kernel/fs/my_drv/my_drv.ko):模块格式无效

[ 在日志消息中: my_drv: 不同意符号 module_layout 的版本 ]

如何在 3.2.0-29 上构建适用于所有 3.2.0 版本的内核模块。

linux linux-kernel
3个回答
6
投票

简而言之:你很难能够编写有用的内核模块,这些模块可以加载到相对广泛的版本的内核中。

当您针对使用

CONFIG_MODVERSIONS
编译的内核构建模块时(如您的情况),对于从内核导出的每个符号,该符号的 CRC(循环冗余检查)存储在模块的文件中。 CRC 是某种“控制和”,它考虑了用于函数参数的类型布局等。例如,如果假设的 struct A 的布局在两个内核中不同,则这些内核中函数
f(struct A *a)
的 CRC 也会不同。
当模块加载到正在运行的内核中时,模块中所有函数的 CRC 都会与内核的 CRC 进行比较。如果它们不同,内核将拒绝加载该模块。要了解有关此机制的更多信息,请参阅内核文档 (

Documentation/kbuild/modules.txt

)。 因此,为了使模块可加载到两个不同的内核中,您只能使用其参数在两个内核中具有相同布局的函数。特别是,如果

struct module

类型的布局不同,则无法为两个内核加载单个模块。


有多种方法可以提供适合多个内核的驱动程序。最简单的方法是传递驱动程序的
sources

并将其添加到 dkms。这样,如果运行的内核没有构建驱动程序,则将使用其源代码

自动
编译驱动程序。


3
投票
Linux 内核模块 API 作为设计选择是不稳定的

这在

Documentation/stable_api_nonsense.txt

 的源代码树中有明确解释。摘要如下:
Executive Summary ----------------- You think you want a stable kernel interface, but you really do not, and you don't even know it. What you want is a stable running driver, and you get that only if your driver is in the main kernel tree. You also get lots of other good benefits if your driver is in the main kernel tree, all of which has made Linux into such a strong, stable, and mature operating system which is the reason you are using it in the first place.

但是一个重要的澄清是:

The kernel to userspace interface is the one that application programs use, the syscall interface. That interface is **very** stable over time, and will not break. I have old programs that were built on a pre 0.9something kernel that still work just fine on the latest 2.6 kernel release. That interface is the one that users and application programmers can count on being stable.

但不用担心!我们友好的 Linux 开发人员在同一份文档中解释了解决方案:

What to do ---------- So, if you have a Linux kernel driver that is not in the main kernel tree, what are you, a developer, supposed to do? Releasing a binary driver for every different kernel version for every distribution is a nightmare, and trying to keep up with an ever changing kernel interface is also a rough job. Simple, get your kernel driver into the main kernel tree (remember we are talking about GPL released drivers here, if your code doesn't fall under this category, good luck, you are on your own here, you leech <insert link to leech comment from Andrew and Linus here>.) If your driver is in the tree, and a kernel interface changes, it will be fixed up by the person who did the kernel change in the first place. This ensures that your driver is always buildable, and works over time, with very little effort on your part.

Linux内核版本宏

尝试使用:

#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)

是否有宏定义来检查Linux内核版本?


-1
投票

通过将版本作为环境变量传递来针对已安装的内核构建模块

例如。

make K_VERSION=`uname -r`

针对当前运行的内核进行构建。

构建完成后,即可使用 modprobe 实用程序。

© www.soinside.com 2019 - 2024. All rights reserved.