当前位置:首页>Linux>Linux probe函数最后调用谁?

Linux probe函数最后调用谁?

  • 2026-10-11 20:07:26
Linux probe函数最后调用谁?
大家好,我是王鸽,在设备树的出现后,发现有些从事驱动工作久的人,只知道设备树修改,编译,出固件,变成“固件工程师”,导致对底层代码阅读能力下降,这个时候面试的时候会一脸尴尬起来,回归正题!
首先,probe何时被调用?即在总线上驱动和设备的名字匹配,就会调用驱动的probe函数。
先说一下platform设备总线驱动模型:
 Device注册过程---device_register()

kernel/drivers/base/core.c

intdevice_register(struct device *dev){	device_initialize(dev);return device_add(dev);                |--error = bus_add_device(dev);                |--bus_probe_device(dev);                     |--if (bus->p->drivers_autoprobe) {  		        ret = device_attach(dev);		        WARN_ON(ret < 0);} } 其中device_attach函数中if (dev->driver) {    ret = device_bind_driver(dev);    }else {	ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);	pm_request_idle(dev);}__device_attach函数中(dd.c)if (!driver_match_device(drv, dev))(base.h)    |--return drv->bus->match ? drv->bus->match(dev, drv) : 1;return driver_probe_device(drv, dev);(dd.c)    |--ret = really_probe(dev, drv);             |---dev->driver = drv;             |--if (dev->bus->probe) {		ret = dev->bus->probe(dev);                if (ret){                goto probe_failed;	        } else if (drv->probe) {		ret = drv->probe(dev);
Driver注册过程---driver_register()
int driver_register(struct device_driver *drv)        |--other = driver_find(drv->name, drv->bus);        |--ret = bus_add_driver(drv);                |--if (drv->bus->p->drivers_autoprobe) {|--error = driver_attach(drv);	            |--return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  其中__driver_attach函数(dd.c)
if (!driver_match_device(drv, dev))return 0;if (dev->parent)	/* Needed for USB */		device_lock(dev->parent);	device_lock(dev);if (!dev->driver)		driver_probe_device(drv, dev);		|----ret = really_probe(dev, drv);		     |---dev->driver = drv;                     |--if (dev->bus->probe) {		        ret = dev->bus->probe(dev);                        if (ret){                        goto probe_failed;	                } else if (drv->probe) {		        ret = drv->probe(dev);

从代码的追踪发现:

bus_for_each_drv()是对BUS上所有的Driver都进行__device_attach()操作;同样的,bus_for_each_dev()是对BUS上所有的Device都进行__driver_attach()操作。

BUS上实现的.match()函数,定义了Device和Driver绑定时的规则。比如Platform实现的就是先比较id_table,然后比较name的规则。如果BUS的match()函数没实现,认为BUS上的所有的Device和Driver都是match的,具体后续过程要看probe()的实现了。

Probe的规则是:如果BUS上实现了probe就用BUS的probe;否则才会用driver的probe。

Device一般是先于Driver注册,但也不全是这样的顺序。Linux的Device和Driver的注册过程分别枚举挂在该BUS上所有的Driver和Device实现了这种时序无关性。
所有驱动的 probe 函数最终都会走到内核通用的 really_probe() 函数中被调用,而不同总线(如 I2C、SPI、PCI)的 probe 只是在这之前有各自的适配层,最终都会收敛到这个核心函数。
# 触发源(二选一)触发源1:驱动注册 → driver_attach() → __driver_attach()触发源2:设备注册 → device_attach() → __device_attach()  → driver_match_device()  // 总线匹配(如I2C的i2c_device_match)    → driver_probe_device()  // 通用probe入口      → really_probe()  // 内核probe核心函数        → ① 执行总线级probe(如有,如I2C的i2c_device_probe)        → ② 最终调用驱动开发者实现的probe函数
int driver_probe_device(struct device_driver *drv, struct device *dev){int ret = 0;if (!device_is_registered(dev))return -ENODEV;	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",		 drv->bus->name, __func__, dev_name(dev), drv->name);	pm_runtime_barrier(dev);	ret = really_probe(dev, drv);	pm_request_idle(dev);return ret;}

核心终点:really_probe()

这是所有驱动 probe 调用的最终核心入口,定义在 drivers/base/dd.c 中,核心逻辑伪代码如下:

staticintreally_probe(struct device *dev, struct device_driver *drv){    int ret = 0;    // 1. 绑定驱动到设备    dev->driver = drv;    // 2. 优先执行总线定义的probe(如I2C总线的i2c_device_probe)    if (dev->bus->probe) {        ret = dev->bus->probe(dev);  // I2C总线会走到i2c_device_probe    }     // 3. 总线无probe时,直接执行驱动自带的probe    else if (drv->probe) {        ret = drv->probe(dev);      // 部分总线直接调用驱动probe    }    // 4. probe成功/失败的后续处理(如添加设备到sysfs)    if (ret == 0) {        dev->probe_done = 1;    } else {        dev->driver = NULL;    }    return ret;}

总线适配层:以 I2C 为例的 i2c_device_probe()

I2C 总线在 dev->bus->probe 中注册了 i2c_device_probe,它是 “内核通用层” 到 “驱动实现层” 的适配,核心逻辑:

staticinti2c_device_probe(struct device *dev){struct i2c_client	*client = i2c_verify_client(dev);// 转换为I2C设备对象struct i2c_driver	*driver;int status;if (!client)return 0;	driver = to_i2c_driver(dev->driver);// 转换为I2C驱动对象if (!driver->probe || !driver->id_table)// 最终调用你写的I2C驱动probe(如xxx_i2c_probe)return -ENODEV;	client->driver = driver;if (!device_can_wakeup(&client->dev))device_init_wakeup(&client->dev,					client->flags & I2C_CLIENT_WAKE);dev_dbg(dev, "probe\n");	status = driver->probe(client, i2c_match_id(driver->id_table, client));if (status) {		client->driver = NULL;i2c_set_clientdata(client, NULL);	}return status;}

最终执行:开发者实现的 probe

// 你写的I2C驱动probestaticintxxx_i2c_probe(struct i2c_client *client, conststruct i2c_device_id *id){    // 设备初始化、申请资源、注册字符设备等逻辑    return 0;}// 驱动结构体中关联static struct i2c_driver xxx_i2c_driver = {    .probe = xxx_i2c_probe,  // 最终被i2c_device_probe调用    .driver = {        .name = "xxx_i2c",    },};

不同总线的差异(核心不变,仅适配层不同)

总线类型
总线级 probe
驱动 probe 原型
最终调用逻辑
I2C
i2c_device_probe
int (*probe)(struct i2c_client *, const i2c_device_id *)
really_probe → i2c_device_probe → 自定义 probe
SPI
spi_device_probe
int (*probe)(struct spi_device *)
really_probe → spi_device_probe → 自定义 probe
PCI
无(直接调用)
int (*probe)(struct pci_dev *, const pci_device_id *)
really_probe → 直接调用自定义 probe
platform
platform_drv_probe
int (*probe)(struct platform_device *)
really_probe → platform_drv_probe → 自定义 probe

总结

调用流程分为三层:① 触发匹配(设备 / 驱动注册)→ ② 总线适配(如 i2c_device_probe)→ ③ 执行开发者自定义的 probe;

大概probe怎么调用就分析到这里,谢谢啊

最新文章

随机文章