How to build a Linux kernel module so that it is compatible with all kernel releases?

前端 未结 3 1027
慢半拍i
慢半拍i 2020-12-19 05:58

I want to build a kernel module that will be compatible with all the kernel’s releases. For example, if I build a kernel module on kernel 3.2.0-29 and try to load it on 3.2.

相关标签:
3条回答
  • 2020-12-19 06:05

    Add an Environment variable to the Makefile viz. 'K_VERSION'.

    Build the module against an installed kernel by passing the version as the environment variable

    eg.

    make K_VERSION=`uname -r`
    

    to build against currently running kernel.

    Once built, the modprobe utility can be used.

    0 讨论(0)
  • 2020-12-19 06:08

    The Linux kernel module API is unstable as design choice

    This is explicitly explained in the source tree at Documentation/stable_api_nonsense.txt. The summary reads:

    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.
    

    But an important clarification is:

      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.
    

    But worry not! Our friendly Linux developers explain the solution right in the same document:

    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 kernel version macro

    Try using:

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

    as mentioned at Is there a macro definition to check the Linux kernel version?

    0 讨论(0)
  • 2020-12-19 06:30

    In short: you hardly can write useful kernel module, which can be loaded to kernels of relatively wide range of versions.

    When you build the module against kernel compiled with CONFIG_MODVERSIONS (like in your case), for every symbol, exported from the kernel, CRC for this symbol is stored in module's file. CRC is some sort of control sum, which takes into account, among other things, layout of types, used for function's parameters. For example, if layout of a hypothetical struct A differs in two kernels, CRC for function f(struct A *a) in these kernels differs too.

    When a module is loaded into running kernel, CRC for all functions in the module are compared with ones for the kernel. If they differ, the kernel refuses to load the module. To read more about this mechanism see the kernel's documentation (Documentation/kbuild/modules.txt).

    So, for make a module loadable into two different kernels, you are restricted only with functions whose parameters have same layout in both kernels. In particular, if layout of type struct module differs, no single module can be loaded for both kernels.


    There are several approaches to deliver a driver suitable for several kernels. The simplest way is to deliver the driver's sources and add them to dkms. Such a way, if running kernel doesn't have the driver built, the driver will be compiled automatically using its sources.

    0 讨论(0)
提交回复
热议问题