
核心要点速览
调用方式:通过总线框架间接调用,不是内核直接调用
匹配条件:设备树compatible属性与驱动of_match_table匹配
调用时机:驱动加载且设备匹配成功时调用,顺序不固定
返回值:成功返回0,失败返回负数错误码,返回错误则驱动绑定失败
常见排查:compatible不匹配、驱动未加载、节点状态disabled、dmesg报错
面试题
Linux设备树驱动的probe函数是什么时候被调用的?调用流程是怎样的?如果probe没被调用,你怎么排查?
回答思路
probe函数调用完整流程
用代码来展示这个调用链的关键节点:
module_platform_driver(my_driver);
/* 向下展开为 */
platform_driver_register(&my_driver);
→ driver_register(&drv->driver);
→ bus_add_driver(drv);
→ driver_attach(drv);
→ __driver_attach(dev, drv);
→ driver_match_device(drv, dev); // 匹配compatible
→ driver_probe_device(drv, dev);
→ really_probe(dev, drv);
→ dev->bus->probe(dev); // 总线probe
→ my_driver.probe(pdev); // 驱动probe
匹配的具体过程
设备树匹配的核心函数是of_driver_match_device。它会遍历驱动的of_match_table数组,把每一项的compatible字符串和设备节点的compatible属性做比较。注意compatible属性是可以有多个值的,设备树里写的是一个字符串列表,从最具体到最通用。内核会按顺序匹配,找到第一个匹配的就算成功。
static const struct of_device_id my_of_match[] = {
{ .compatible = "vendor,my-chip-v2" },
{ .compatible = "vendor,my-chip" },
{ },
};
/* 设备树侧 */
my_device@1000 {
compatible = "vendor,my-chip-v2", "vendor,my-chip";
reg = <0x1000 0x100>;
};
面试官追问
第一步,看驱动有没有加载成功。用lsmod命令看模块在不在,或者dmesg看有没有模块加载的日志。如果模块都没加载成功,那probe肯定不会调用,先解决加载问题。
第二步,检查设备树节点。用ls /sys/bus/platform/devices/看设备有没有被正确创建。如果设备节点不存在,可能是设备树编译没包含进去,或者节点status是disabled状态。
第三步,核对compatible字符串。这是最常见的问题。设备树里写的和驱动of_match_table里的必须完全一致,大小写、连字符、厂商前缀都不能错。我就遇到过vendor前缀写错的问题,排查了半天才发现。
第四步,加调试打印。在probe函数最开头加一句pr_err打印,如果dmesg里没有这句,说明没进probe。还可以在probe之前的匹配函数里加打印,定位是哪一步出了问题。
第五步,检查其他可能因素。比如是不是驱动返回了EPROBE_DEFER(因为依赖的资源还没准备好),这种情况probe会被延后调用。还有是不是设备已经被其他驱动绑定了。
-ENODEV:设备不存在或不支持
-ENOMEM:内存分配失败
-EIO:硬件IO错误
-EPROBE_DEFER:依赖的资源还没准备好,需要延迟probe
如果probe返回错误,总线就会认为绑定失败,驱动不会和这个设备绑定。特别是EPROBE_DEFER这个返回值很重要,如果probe中申请的资源(比如时钟、gpio、regulator)还没就绪,就返回EPROBE_DEFER,内核会把这个设备放到延迟队列里,等其他驱动加载完了再重新尝试probe。
具体来说:如果先加载驱动、后创建设备(比如设备树节点后面才注册),那么设备注册的时候会遍历总线上的驱动,找到匹配的就调用probe。反过来,如果设备已经存在了、驱动后加载,那么驱动注册的时候会遍历设备,找到匹配的就调用probe。
所以probe的调用时机不是固定的,取决于驱动和设备谁先出现在总线上。这也是为什么有些设备的probe调用顺序不固定,依赖加载顺序。对于有依赖关系的驱动,就要用EPROBE_DEFER机制来处理。
"okay"或"ok":设备正常可用,会被正常创建和匹配
"disabled":设备被禁用,不会被创建,也就不会调用probe
"fail"或"fail-xxx":设备故障,不可用
最常用的是okay和disabled。很多时候同一款芯片用在不同产品上,有的产品用了某个外设有的没用到,就可以通过修改status来控制设备要不要启用。disabled的设备节点,内核不会为它创建platform_device,自然也就不会匹配驱动和调用probe了。
失分表达
常见失分回答
"系统启动的时候调用的" —— 太含糊,说明你对驱动模型不了解
"内核直接调用probe函数" —— 不对,是通过总线框架间接调用的
"没调用就是compatible写错了" —— 只说这一个原因,排查思路不全面
"probe返回0和返回1没区别吧" —— 有区别,非0就是失败,驱动绑定不上
准备动作
对照内核源码,跟踪一遍platform_driver_register的调用路径
亲手写一个最简单的platform驱动,加各种打印,看dmesg输出
故意写错compatible,观察驱动加载后的现象,积累排查经验
了解一下EPROBE_DEFER的机制和使用场景
准备一个你实际调试过的驱动问题,讲清楚排查过程
核心关键词
Linux设备树、probe函数、platform驱动、驱动注册、compatible匹配、driver_register、嵌入式Linux面试

扫码关注



























