How to Build a Linux Kernel Module So That It Is Compatible with All Kernel Releases

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

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.

Building kernel modules for different linux version

So, building a new kernel is not a good option as it will require :

  • building kernel
  • building modules and firmware
  • building headers
    Moving all of above things in appropriate location (if your machine is not same on which you are going to develop module)

So if you have kernel headers for running system then you dont need to download a source code for any kernel version, and while making module use

make -C /lib/modules/kernel-headers-x.y.z/build M=`pwd` modules

and your module will be ready.

If there would be better answers, i will not hesitate to accept any of them.

Linux Kernel Module (*.ko) compatibility between kernels

Joe, Ubuntu (3.2) maybe using kernel version x.y.z but Ubuntu (3.9) maybe using kernel version x.y.z1. If kernel versions differ you must need to build/compile your driver against that particular kernel version. If the kernel versions are same then no need to build your driver. Important point is that every driver module is been compiled or built linking with version.ko module (which actually embeds the information about the kernel version the driver module built against), while loading kernel module it checks for this information and kernel version, if different then throws "-1 Invalid module format" or if matched then kernel module is loaded successfully. To develop kernel module which is future or backward compatible you need to know on which kernel version which API's or functions signature have been changed for ex: ioctl signature changed from kernel version 2.3.36 onwards, so your code should be as below

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
static long minor_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
#else
static int minor_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
#endif

If developed in such a way then your kernel module is future or backward compatible. Compatibility is only adaptation of API's or function signature etc.. changes for the kernel version by preserving the older API's or function signature etc.. in your kernel module as in the above example, but still you need to build/compile your kernel module against the kernel version on which you are trying to load.

Linux Kernel Module development compile for other kernel


I've downloaded kernel version 3.16.xx from https://www.kernel.org/ and then pointed to extracted files from that archive.

You can't compile modules for some kernel if you have only its original source. You need point IDE to configured and partially build kernel. Actually, all files needed to build modules for some kernel version are in kbuild directory of compiled kernel, installed into /lib/modules/version/kbuild. There are linux-kbuild-version (https://packages.debian.org/jessie/kernel/linux-kbuild-3.16) package with some files https://packages.debian.org/jessie/amd64/linux-kbuild-3.16/filelist and linux-headers-version (https://packages.debian.org/jessie/linux-headers-3.16.0-4-amd64) which includes Module.symvers (https://packages.debian.org/jessie/amd64/linux-headers-3.16.0-4-amd64/filelist):

/usr/src/linux-headers-3.16.0-4-amd64/Module.symvers

how to write cross-version/platform Linux kernel modules?

Linux, the ying and the yang. Tangrs answer is good; it answers your question. However, there is the linux compat projects. See the backports wiki. Basically, there are libraries that provide shim functionality for newer Linux ABI's which you can use to link your code. The KERNEL_VERSION macro that Eugene notes is inspected in a compat.h, and appropriate compat-2.6.38.h, etc are included where each version has either macros and/or library functions to provide a forward API.

This lets the Linux Wifi group write code for the bleeding edge kernel, while still making it possible to compile on older kernel versions.

I guess this answers the question,

if there are any standard ways to deal with versioning?

The compat library is not a panacea, but at least it is there and under development.

Open source - There are many mutations. They all have a different plan.



Related Topics



Leave a reply



Submit