对于标准内核本身(https://kernel.org),同一个函数的类型,或者同一个结构中的成员,在不同版本中,可能是有变化的;
操作系统发行厂商(RedHat、Centos、Ubuntu等),会对内核进行backporting,比如CentOS-8.2中的内核版本为4.18.0-193.28.1,其中的DRM内核模块,是从5.3.0内核(版本>4.18.0),backporting过来的。
Autoconf不是根据版本号,而是通过试探性编译,判断函数类型。这样,一方面可以使驱动开发者,只需要关注函数有哪些类型,不需要关注每种类型对应哪些内核版本;另一方面也消除了backporting的问题(比如以上CentOS-8.2的例子,要同时结合内核和系统发行版本,才能确定DRM内核模块的版本,这会使版本判断逻辑十分臃肿)。
参考:https://zhuanlan.zhihu.com/p/570218272
很多开源代码,通过执行“./configure; make; make install”,即可完成编译安装,其中,configure脚本执行时,一般会检查当前环境,是否安装了gcc、make等,有时候还会生成一个config.h头文件(内容通常受当前环境的glibc版本等因素影响),这个过程,其实就相当于将源码,动态适配到当前环境。
Configure实质上就是一个shell脚本,由autoconf命令生成,以下引用一张网络上搜索到的图片:
了解各个文件生成过程,只需要顺着依赖关系往回看即可,比如config.h:
1 2 3 4 5 6 7 8 9 10 |
|
可以看出,为了生成config.h,只要提供configure.ac、m4文件,并执行autoreconf命令(相当于aclocal+autoheader+autoconf的组合)即可,并且,如果自定义的宏不多,可以直接写在configure.ac文件,m4文件是可选的。
configure.ac和m4文件,本质上是还未展开的shell脚本,文件内部既可以定义宏,也可以调用宏(和c语言中的宏,概念相同,只不过定义和展开规则不同),这些宏最终都会由autoconf内部执行的m4命令展开,其中,m4程序本身内置了一些宏,autoconf程序也内置了一些专用于生成configure的宏。
m4宏的定义语法和展开规则,可以执行“info autoconf”,或在线查看gnu官方文档。
官方文档:https://www.gnu.org/software/autoconf/manual/autoconf-2.60/html_node/index.html#Top
组件关系:https://www.cnblogs.com/Janly/p/14434914.html
M4中文教程:https://segmentfault.com/a/1190000004104696
网上大量的文章,都只介绍了利用autoconf适配glibc函数的方法,但是直接套用于内核函数的适配,会遇到很多问题,面对大量的内置宏和晦涩的m4语法,尝试替换宏和各种写法之后,都没解决,所以最后决定套用rocm(AMD显卡驱动)代码中的用法。
附件中的打包文件,是对rocm驱动中dkms目录的简化:
首先是删除了m4目录中大量的.m4文件(access-ok.m4也可以删除,保留只是为了测试是否能正确检查access_ok()内核函数的类型),其次是抽离使用会报一些错误,所以还注释了pre-build.sh脚本中的一些片段,kernel.m4和sources文件也被注释了一些内容,具体修改可以通过diff等工具对比。
dkms.conf也可以删掉,它用于内核升级后,自动触发autoconf,以及后续的驱动编译、加载,和autoconf属性完全独立的功能,但在开源驱动中,经常结合autoconf一起使用。
rocm:https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/tree/rocm-5.4.4/drivers/gpu/drm/amd/dkms
Autoconf只是用于生成Makefile、config.h,至于何时触发,以及根据config.h对驱动进行重新编译、加载,就是通过dkms完成,不难理解。
使用:https://blog.51cto.com/woshiyu001/2952596
原理:https://blog.csdn.net/weixin_34626306/article/details/112109849
github:https://github.com/dell/dkms
知乎大佬兰新宇的指导:
以及他的文章:https://zhuanlan.zhihu.com/p/570218272