问题描述
使用insmod命令加载编写的驱动模块时,出现提示信息:loading out-of-tree module taints kernel。不过,模块还是能够被加载。并且卸载后再次加载时,该提示信息没有再次出现。然而整个系统重启后再加载模块,仍然会出现该提示信息。也就是说,在linux的一次运行期间,加载自己编写的驱动模块时,出现了上述提示信息。
原因分析
提示信息中的taint是污染的意思,整个提示信息的意思是加载树外模块污染内核。先简单说一下内核污染,当内核受到污染意味着内核处于社区不支持的状态,并且内核提供的某些功能可能会被禁用。此时,如果内核运行出现问题,内核开发者是不会理会的。
为什么要搞这样一个机制呢?简单点说,有一个对linux感兴趣的同学下载了kernel的源码并移植到自己的开发板上,然后自己写驱动,并加载到内核。之后的一个时间点,假如内核运行出现了问题,此时该同学是不应该向内核开发者反应问题的。因为很有可能内核本身没问题,而是这个同学自己写的驱动存在问题,导致了内核的崩溃。内核开发者仅仅只审核了位于内核源码树中的代码,因而只对源码树中的代码负责。换句话说,一个被污染的内核出现问题可能不是内核的bug;一个没有被污染的内核的错误报告更可能蕴含内核bug。有了这个机制,内核开发者就可以确定哪些错误报告是需要处理的,不然查半天发现不是自己的问题,这就耽误工夫了。
这里列部分内核被污染的原因:
加载非GPL兼容的内核模块
staging驱动程序的使用,它们是内核源代码的一部分,但尚未经过全面测试
使用内核源代码未包含的树外模块
强制加载不是为当前内核版本构建的模块
某些严重错误,例如machine check exceptions(MCE)和kernel oopses
显然,本文所述的内核被污染的原因是加载了树外模块,也就是加载自己写的驱动,不在内核源码树中。更多关于内核污染的信息,可以参考这个问答:What is a tainted kernel in Linux?
现在,我们再来思考一个问题,内核是怎么知道这个模块是树外的?对此,有人讨论过:Marking loadable kernel module as in-tree。这里我简单总结一下,我们在编译驱动模块的Makefile中使用M=$(PWD)来指定驱动源码所在的目录,内核的顶层Makefile在检查到M非空时,会设置KBUILD_EXTMOD变量,最终导致内核的编译体系不会在modulename.mod.c中添加MODULE_INFO(intree, "Y");,也就是说不会给我们自己的驱动打上属于树内的标记。
解决方案
大多数情况下,我们可以忽略内核污染的情况,不能忽略的只是某些严重的系统问题导致的内核。事实上,尽管加载内核时会有上述提示,但终究成功加载了模块,驱动也能工作。
强迫症患者可能非要寻找一个解决方法,那么我们对症下药,可以使用这么几种解决方案:
向内核提交patch,让内核的开发者将你的驱动并入内核源码树(对于只是学习驱动的情况,这个方法并不合适)
自己把驱动程序拷贝到本地的源码树中,并自己添加相应的内核配置项,然后在树内编译驱动模块(保持M为空,这样做也挺麻烦的)
自己在驱动源码种添加一句MODULE_INFO(intree, "Y");,以欺骗内核本模块为树内模块(最好不要这么搞)
综上,强迫症患者还是忍忍吧,对于自己学习驱动从而产生一些树外模块的情况,忽略上述提示信息就可以了^_^!!
最后的最后,我看到网上有同学说这个跟模块的签名有关,但就我找到的资料来看,好像不是这么回事,毕竟当前我并未启用linux内核中的模块签名验证:
# CONFIG_MODULE_SIG is not set
1
既然提到了模块签名,就再丢一个链接:Signed kernel module support。这里对模块签名有更多的说明,感兴趣的同学可以去看看。
————————————————
版权声明:本文为CSDN博主「冉冉云」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/gzxb1995/article/details/105407014