i40e: version magic '4.4.58-svn-46674 SMP mod_unload modversions aarch64' should be '4.4.131.kylin.server.YUN SMP mod_unload aarch64'
一校招生在insmod ko的時候總是遇到此問題, 當時就給了答案就說 了 config 配置文件中 某某字段 不對--->內核 svn版本 不對
問題很好解決!
目前來看下這個version magic的內核實現
根據打印log信息看,是由version magic不匹配造成,找到信息打印點
static int check_modinfo(struct module *mod, struct load_info *info, int flags) { const char *modmagic = get_modinfo(info, "vermagic"); int err; if (flags & MODULE_INIT_IGNORE_VERMAGIC) modmagic = NULL; /* This is allowed: modprobe --force will invalidate it. */ if (!modmagic) { err = try_to_force_load(mod, "bad vermagic"); if (err) return err; } else if (!same_magic(modmagic, vermagic, info->index.vers)) { pr_err("%s: version magic '%s' should be '%s'\n", mod->name, modmagic, vermagic); return -ENOEXEC; } ------------------------------------------- }
當前module ko的modmagic 和 內核的vermagic 對比;
static const char vermagic[] = VERMAGIC_STRING; #define VERMAGIC_STRING \ UTS_RELEASE " " \ MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \ MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \ MODULE_ARCH_VERMAGIC \ MODULE_VERMAGIC_RETPOLINE #define MODULE_ARCH_VERMAGIC "aarch64" #define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload " #define MODULE_VERMAGIC_PREEMPT "preempt " #define MODULE_VERMAGIC_MODVERSIONS "modversions " #define MODULE_VERMAGIC_SMP "SMP "
VERMAGIC_STRING 中的UTS_RELEASE 指向啥呢??
這個是在Makefile中定義!
#define UTS_RELEASE \"$(KERNELRELEASE)\";)
# Read KERNELRELEASE from include/config/kernel.release (if it exists) KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
可見KERNELRELEASE由include/config/kernel.release文件讀取獲得,此文件是編譯生產的,在原始的內核代碼中沒看到,但是make 后就能看到!
Q2:在查看 same_magic 函數實現的時候發現有兩個函數實現, 通過CONFIG_MODVERSIONS 宏來控制
- 如果宏沒有開啟,將對vermagic作全字符串的完整匹配,任何不一致均會阻止該內核模塊的加載;
- 而倘若這個宏被開啟,則只有vermagic第一個空格之后的部分會參與匹配
PS:在對比的時候發現 4.4.131.kylin.server.YUN SMP mod_unload aarch64 這段字符中沒有看到 #define MODULE_VERMAGIC_PREEMPT "preempt "
也就是沒有開啟 CONFIG_PREEMPT
回歸正題, 那 kernel.release是怎樣生成的呢?
define filechk_kernel.release
echo $(KERNELVERSION)$$(if [ "$(FROM_DPKG)" != y ]; then $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree);fi)
endef
# Store (new) KERNELRELEASE string in include/config/kernel.release
include/config/kernel.release: include/config/auto.conf FORCE
$(call filechk,kernel.release)
看Makefile 中 可以看到 依賴於setlocalversion 腳本
也就是 只需要執行 setlocalversion 這個腳本就知道 version magic 的生成了!!