Linux内核模块加载及更新问题
Linux内核模块加载及更新问题
背景
最近碰到了一个Linux内核模块更新问题,比较有意思,特此记录。
问题: 一款我们内核已经适配过的蓝牙模块在一台机器上用不了,驱动加载不起来,看内核日志报一堆的符号问题:
29.784454] rtk_btusb: Unknown symbol hci_free_dev(err -22)
29.784483] rtk_btusb: disagrees about version of symbol hci_alloc_dev_priv
29.784484] rtk_btusb: Unknown symbol hci_alloc_dev_priv(err-22)
29.784571] rtk_btusb: disagrees about version of symbol hci_unregister_dev
29.784573] rtk_btusb: unknown symbol hci_unregister_dev (err -22)
29.784583] rtk_btusb: disagrees about version of symbol hci_recv_frame
29.784584] rtk btusb: unknown symbol hci_recv_frame (err -22)
29.784608] rtk_btusb: disagrees about version of symbol hci_register_dev
29.784610] rtk_btusb: Unknown symbol hci_register_dev (err -22)
29.784618] rtk_btusb: disagrees about version of symbol _hci_cmd_sync
29.784620] rtk btusb: Unknown symbol_hci_cmd_sync(err-22)
29.808471] rtk_btusb: disagrees about version of symbol hci_free_dev
...
分析
从内核日志来看很明显是内核和驱动模块不匹配导致,但是内核包是用的我们正式发布的版本,按道理来说应该不会出现这种最低级的问题,于是开始一步步排查。
- 确认系统带的蓝牙驱动是否手动升级或修改
进入/lib/modules/xxx-generic/kernel/drivers
目录,确认使用的蓝牙内核模块也未手动升级或修改,是和内核包一起的模块。 - 手动加载驱动模块验证
首先手动modprobe xxx
这个驱动,发现加载报错;
然后我直接手动insmod
了一下这个蓝牙驱动(/lib/modules/xxx-generic/kernel/drivers
目录下的),惊奇地发现居然成功加载了,而且蓝牙可以正常使用了。
难道是系统之前使用的蓝牙驱动不是这个目录下的? - 确认是否有其他同名驱动
带着前面的疑问,我在/lib/modules/xxx-generic/
目录查找了一番,果然发现新大陆,在/lib/modules/xxx-generic/updates/
下也有一个同名的驱动 - 确认是否是
updates/
目录下的同名驱动引起
难道现在系统使用的是updates/
目录下的驱动?
于是直接手动insmod
了一下该目录下的同名驱动,报错;
然后我将该驱动mv
掉,然后depmod
,再modprobe
这个驱动,成功了!果然是这个updates/
目录下的同名驱动引起的。
至此问题解决!
扩展updates
目录
有时候 Linux 内核模块有更新,或者有第三方的改动需要用,要替换原来的模块。
比较简单的方法是把原来的 *.ko 文件直接替换,但这样有不好的地方,如果想换回来,比较麻烦。
较好的方法是把模块装在 /lib/modules/
uname -r
/updates/ 下面,再运行 depmod,这样下次开机自动加载模块,或者用 modprobe 加载模块时,就会用 updates 下面的
后面有时间想仔细去看看modprobe
的加载机制和流程。最近事情太多,先到这。
参考
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 DD'Notes!
评论