拓冰建站拓冰建站
首页 / 资讯中心 / 正文

驱动模型匹配:从 driver_register 到bus->match/probe 的绑定路径

设备在/sys里看得见却不probe、compatible对了仍不绑驱动根因常在bus/device/driver 三件套的匹配与绑定而不是probe函数体本身。本文沿driver_register→bus_add_driver→driver_attach→bus-match→probe走通一次绑定便于对照 sysfs 与 DT 排障。源码锚点路径作用include/linux/device/driver.hstruct device_driver、driver_registerinclude/linux/device/bus.hstruct bus_typematch/probe/removeinclude/linux/device.hstruct device、device_registerdrivers/base/driver.cdriver_register/driver_attachdrivers/base/bus.cbus_add_driver、匹配与遍历drivers/base/dd.cdevice_attach/__device_attach/really_probeinclude/linux/mod_devicetable.hof_device_id等匹配表核心结构头文件可见字段/* include/linux/device/bus.h */structbus_type{constchar*name;int(*match)(structdevice*dev,structdevice_driver*drv);int(*probe)(structdevice*dev);int(*remove)(structdevice*dev);/* … */};/* include/linux/device/driver.h */structdevice_driver{constchar*name;structbus_type*bus;structmodule*owner;conststructof_device_id*of_match_table;int(*probe)(structdevice*dev);int(*remove)(structdevice*dev);/* … */};注册骨架/* 典型写法把 driver 挂到对应 bus */staticstructdevice_drivermy_drv{.namemy-drv,.busplatform_bus_type,/* 或 pci_bus_type 等 */.ownerTHIS_MODULE,.of_match_tablemy_of_match,.probemy_probe,.removemy_remove,};driver_register(my_drv);/* 内部 bus_add_driver → driver_attach */调用链驱动加载 / 内置 init → driver_register(drv) /* drivers/base/driver.c */ → bus_add_driver(drv) /* drivers/base/bus.c */ → driver_attach(drv) → 遍历 bus 上已有 device → driver_match_device() /* 调 bus-match */ → device_driver_attach / really_probe → drv-probe(dev) 或 bus-probe 设备侧后注册热插拔 / 晚枚举 → device_register(dev) → bus_probe_device / device_initial_probe → 对已注册 driver 再跑 match → probeDevice Tree 场景platform 常见of_platform_populate / 创建 platform_device → device 挂上 platform_bus → bus-matchof_driver_match_device看 compatible → 命中后进入 probe重点知识1. 匹配键在 bus不在「文件名像不像」bus-match决定能否绑platform 看of_match_table/namePCI 看 ID 表USB 看 vid/pid。只改模块名、不改 match 表永远不会probe。2.driver_register与device_register谁先谁后都要能绑模型支持双向先有设备后有驱动或反过来。driver_attach/device_attach保证后注册的一方仍会遍历匹配。排障时两边都要查/sys/bus/bus/devices与drivers。3.probe失败会留下「半绑定」观感really_probe里probe返回非 0 会解绑并可能打 defer-EPROBE_DEFER。依赖时钟/regulator/GPIO 未就绪时应用 defer而不是假装成功反复 defer 要查依赖图与 DT 资源。4. 观测与配置ls/sys/bus/platform/devices/ls/sys/bus/platform/drivers/# 看是否已 bindls-l/sys/bus/platform/devices/dev/driver# DT compatiblecat/proc/device-tree/.../compatible# 若启用 proc DT# 强制 bind/unbind调试echodevice|sudotee/sys/bus/platform/drivers/drv/binddmesg|grep-iEprobe|defer5. 设计意图与踩坑意图用统一 kobject/sysfs 拓扑表达硬件把「发现」与「驱动逻辑」解耦。坑compatible字符串与of_match_table不一致多一个厂商前缀就 miss。坑owner/module引用错误probe后模块可被卸载。坑在probe里睡眠过久占着绑定路径拖慢整条 bus 枚举。坑忽略-EPROBE_DEFER当成永久失败反复改 DT。Checklist能画出driver_register→match→really_probe→drv-probe的链/sys/bus/bus/drivers/name存在且目标 device 的driver软链正确DTcompatible或 PCI/USB ID与 match 表逐字符一致probe失败路径可重入资源获取失败优先-EPROBE_DEFER模块owner与remove成对卸载无 UAFdmesg能对应到本次 bind/probe 日志而非只看业务 printk
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门