在工作中经常会遇到内核升级,开发的代码需要适配的问题。比如本次项目,要使用最新的内核4.19,而之前我们稳定的版本是4.1内核,从4.1到4.19,内核其实变化很大。基于内核开发的一些用户态程序,或者内核模块,当内核升级后,产生的接口变化,会导致这些开发的项目无法编译成功,或者编译成功后无法加载模块,或者出现功能异常的问题。那么就需要基于4.19这个内核,对于接口的变更,要做些适配。
1、编译遇到的问题:
很多接口变更问题,在编译阶段就可以发现了。
遇到的问题举例如下:
unknown type name 'compat_time_t' ##头文件变更 'struct module' has no member named 'module_core' ##结构体变更 too many arguments to function 'pagevec_init' ##函数入参变化 implicit declaration of function ##函数定义取消 error: 'struct stackframe' has no member named 'sp' ##结构体变更 error: implicit declaration of function 'sys_close' ##函数重命名
这些变化,可以从社区找到,根据社区的修改记录,我们找到变更原因,然后按照社区的修复记录来修改就可以了。如何查找社区变更记录可以参考https://www.cnblogs.com/xingmuxin/p/9837849.html
2、加载模块遇到的问题:
解决编译问题后,在插入模块时,又报了错,提示如下错误:
Unknown symbol get_kernel_modules
Unknown symbol nsec_to_clock_t
Unknown symbol security_add_hooks
出现这些问题的原因是这些函数符号,没有使用EXPORT_SYMBOL宏导出,所在其他模块引用这些函数时,无法找到对应的符号地址,所以报了unknown symbol的错误。
其中,security_add_hooks在4.1内核时,在头文件中定义的是一个static inline类型的函数,到了4.19,该函数被写在了其他的c文件中,在头文件中extern声明。头文件中定义为static inline函数时,我们直接include头文件就可以引用这个函数了,但是如果是在c文件中定义的这个函数,在头文件中extern了这个函数,即使我们include了这个头文件,在插入模块后,依然还是会报未定义符号的错误。
修改这样的问题时,我们需要在这个函数定义的内核的.c文件中,加入EXPROT_SYMBOL(),然后重新编译内核。
另外要注意,不仅仅是函数符号,即使是变量,被外部使用的话都需要EXPORT_SYMBOL。
关于EXPORT_SYMBOL的问题可以参考如下:
EXPORT_SYMBOL宏的使用时出现在Linux-2.6之后,在Linux-2.4内核中,默认的非static函数和变量都会自动导入到kernel 空间, 不用EXPORT_SYMBOL() 做标记。然而Linux-2.6之后默认不导出所有符号,所以需要使用EXPORT_SYMBOL() 做标记。
https://blog.csdn.net/zengxianyang/article/details/50611828