前言
随着内核的升级,内核驱动会不兼容,为了让驱动能够兼容新内核和旧内核,需要判断内核的版本。
一 内核版本定义的头文件
下面是5.15版本内核的./include/generated/uapi/linux/version.h文件的内容,该文件是内核编译后自动生成的。
#define LINUX_VERSION_CODE 331591
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#define LINUX_VERSION_MAJOR 5
#define LINUX_VERSION_PATCHLEVEL 15
#define LINUX_VERSION_SUBLEVEL 71
下面是4.1版本内核的./include/generated/uapi/linux/version.h文件的内容
#define LINUX_VERSION_CODE 262415
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
两个文件相同的部分是KERNEL_VERSION宏和LINUX_VERSION_CODE宏。
二 测试验证
写测试驱动,输出KERNEL_VERSION(5,15,71)的值,根据ldd3介绍的KERNEL_VERSION(5,15,71)的值是331591。
测试代码:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>
#define DEBUG_CT(format, ...) printk("%s:%d "format"\n",\
__func__,__LINE__,##__VA_ARGS__)
static int __init ct_init(void)
{
#if KERNEL_VERSION(5,15,71) == LINUX_VERSION_CODE
DEBUG_CT("new version 5");
#else
DEBUG_CT("old version4");
#endif
DEBUG_CT("KERNEL_VERSION(5,15,71) = %d",KERNEL_VERSION(5,15,71));
DEBUG_CT("KERNEL_VERSION(4,1,15) = %d",KERNEL_VERSION(4,1,15));
return 0;
}
static void __exit ct_exit(void)
{
DEBUG_CT("bye bye");
}
module_init(ct_init);
module_exit(ct_exit);
MODULE_LICENSE("GPL");
Makefile文件:
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
#KERN_DIR = /home/lkmao/imx/linux/linux-imx
KERN_DIR = /big/imx/linux-imx-lf-5.15.y
FILE_NAME=csi_timer
obj-m += $(FILE_NAME).o
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
cp:
sudo scp $(FILE_NAME).ko root@192.168.0.3:/home/root/
.PHONY:clean
clean:
make -C $(KERN_DIR) M=$(shell pwd) clean
运行结果:
root@localhost:~# insmod csi_timer.ko
[ 1295.792186] ct_init:12 new version 5
[ 1295.795910] ct_init:16 KERNEL_VERSION(5,15,71) = 331591
[ 1295.801072] ct_init:17 KERNEL_VERSION(4,1,15) = 262415
root@localhost:~#
验证OK。
三 版本区分
可以利用下面的代码根据linux内核版本号的不同调用不同的API函数:在内核源码中所有KERNEL_VERSION可以找到很多区分版本的示例代码。
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0)
....//5.15版本 之前的API调用
#else
....//5.15版本 之后的API调用
#endif
小结
版本,版本。