Linux内核驱动加载时->probe()函数未被调用问题求解
故障原因
probe函数未被触发是三处代码错误导致的:
- 驱动注册接口使用错误:
platform_driver_probe()是内核为编译进内核镜像、启动早期初始化的非热插拔平台驱动设计的接口,该接口在驱动注册完成后会立即扫描当前已存在的平台设备,执行完probe后就会清除驱动的probe指针,后续设备树匹配、延迟探测(deferred probe)场景下都不会再调用probe,完全不支持编译成模块动态加载的驱动场景。 - 缺少模块设备表导出声明:驱动未添加
MODULE_DEVICE_TABLE(of, ubv_match_table)宏,模块加载时内核无法读取设备树匹配表,无法完成设备和驱动的配对。 - 设备树节点不规范:自定义外设节点直接挂在设备树根节点下、缺少
status属性,且compatible字段未按内核规范添加厂商前缀,容易出现匹配失败、节点未被内核识别的问题。
修复步骤
1. 修改驱动注册逻辑
将初始化函数中错误的platform_driver_probe调用替换为标准的平台驱动注册接口,修改后的ubv_init代码如下:
static int __init ubv_init(void) { int ret; printk(KERN_ALERT "%s\n", __FUNCTION__); ret = platform_driver_register(&ubv_platform_driver); printk(KERN_ALERT "ret = %d\n", ret); pr_info("ret = %d\n", ret); return ret; }
2. 添加设备匹配表导出
在ubv_platform_driver定义后方添加如下宏,导出设备树匹配表:
MODULE_DEVICE_TABLE(of, ubv_match_table);
同时建议在匹配表中添加符合内核规范的带厂商前缀的兼容值,避免和其他驱动重名冲突:
static struct of_device_id ubv_match_table[] = { { .compatible = "yourvendor,ubv" }, // 替换为实际厂商名 { .compatible = "ubv" }, {} };
3. 修正设备树节点
将外设节点移动到SoC总线节点下(不要直接挂在设备树根节点),补全status属性,参考配置如下:
// 引用SoC总线节点,将外设作为其子节点 &soc { ubv@96002000 { compatible = "yourvendor,ubv", "ubv"; reg = <0x0 0x96002000 0x0 0x2000>; status = "okay"; no-map; // 仅当不需要内核为该寄存器区域创建线性映射时保留 }; };
验证方法
- 重新编译设备树,替换开发板上的dtb文件后重启系统
- 重新编译驱动模块,执行
insmod加载模块 - 执行
dmesg | grep ubv查看日志,即可看到probe函数的打印信息 - 如果仍未触发probe,先执行
ls /sys/bus/platform/devices/ | grep ubv确认设备节点是否被内核正确识别:- 如果设备节点不存在,检查设备树编译、加载是否正确
- 如果设备节点存在,检查驱动模块的匹配表是否正确导出、compatible字段是否和设备树完全一致
内容的提问来源于stack exchange,提问作者Abhishek Pandey
相关产品推荐
相关产品推荐

