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

时间:2016-05-08 09:49:42

标签: linux linux-kernel

我想构建一个与所有内核版本兼容的内核模块。 例如,如果我在内核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):模块格式无效

     

[在log messeges中:my_drv:不同意有关符号module_layout的版本]

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

3 个答案:

答案 0 :(得分:4)

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

当您针对使用deserializeJSON()编译的内核构建模块时(就像您的情况一样),对于从内核导出的每个符号,此符号的CRC都存储在模块的文件中。 CRC是某种控制和,它除了其他之外还考虑了用于函数参数的类型布局。例如,如果假设public class Main { public static void main(String[] args) { Document doc, content; try { doc = Jsoup.connect("http://fmi.unibuc.ro/ro").get(); System.out.print(doc); Elements links = doc.select("a[href]"); for (Element link : links) { System.out.println("\nlink : " + link.attr("href")); } } catch (IOException e) { e.printStackTrace(); } } } 的布局在两个内核中不同,则这些内核中函数CONFIG_MODVERSIONS的CRC也不同。

当模块加载到运行内核时,模块中所有函数的CRC与内核的CRC进行比较。如果它们不同,则内核拒绝加载模块。要阅读有关此机制的更多信息,请参阅内核的文档(Documentation/kbuild/modules.txt)。

因此,为了使一个模块可以加载到两个不同的内核中,仅限于两个内核中参数具有相同布局的函数。特别是,如果类型struct A的布局不同,则不能为两个内核加载单个模块。

有几种方法可以提供适合多个内核的驱动程序。最简单的方法是提供驱动程序的来源并将其添加到f(struct A *a)。这样一来,如果运行内核没有内置驱动程序,驱动程序将使用其源自动编译

答案 1 :(得分:0)

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.

严重的是,请尝试使用Is there a macro definition to check the Linux kernel version?

中提到的#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)

答案 2 :(得分:-1)

将环境变量添加到Makefile即。 &#39; K_VERSION&#39;

通过将版本作为环境变量

传递,针对已安装的内核构建模块

例如

make K_VERSION=`uname -r`

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

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