利用autoconf自动适配内核函数
2023-4-1 18:21:25 Author: bbs.pediy.com(查看原文) 阅读量:11 收藏

1. 初衷

1.1. 内核适配起因

  对于标准内核本身(https://kernel.org),同一个函数的类型,或者同一个结构中的成员,在不同版本中,可能是有变化的;

1.2. 内核适配面临困难

  操作系统发行厂商(RedHat、Centos、Ubuntu等),会对内核进行backporting,比如CentOS-8.2中的内核版本为4.18.0-193.28.1,其中的DRM内核模块,是从5.3.0内核(版本>4.18.0),backporting过来的。

1.3. 利用autoconf适配内核初衷

  Autoconf不是根据版本号,而是通过试探性编译,判断函数类型。这样,一方面可以使驱动开发者,只需要关注函数有哪些类型,不需要关注每种类型对应哪些内核版本;另一方面也消除了backporting的问题(比如以上CentOS-8.2的例子,要同时结合内核和系统发行版本,才能确定DRM内核模块的版本,这会使版本判断逻辑十分臃肿)。

参考:https://zhuanlan.zhihu.com/p/570218272

2. Autoconf概念

  很多开源代码,通过执行“./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脚本

 |   |- configure.ac

 |   |- aclocal.m4

 |   |   |- 自定义的m4文件  # 所在目录通过AC_CONFIG_MACRO_DIR宏指定

 |   |   |- aclocal命令

 |   |- autoconf命令

 |- config.h.in

     |- AC_DEFINE宏     # 根据configure.ac,最终展开过AC_DEFINE宏

     |- autoheader命令

  可以看出,为了生成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

3. Autoconf在rocm-5.4.4显卡驱动中的应用

  网上大量的文章,都只介绍了利用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

4. 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

IDA 特训营

上传的附件:
  • dkms-test0.tar.gz (47.52kb,2次下载)

文章来源: https://bbs.pediy.com/thread-276707.htm
如有侵权请联系:admin#unsafe.sh