Linux内核中从无关驱动B检测驱动A是否成功探测
Linux驱动中通过驱动名称判断探测状态并触发函数的实现方法
可以实现,以下是几种常用的方案:
方案一:通过sysfs/class/总线查找设备状态
驱动A探测成功后会将对应的设备注册到系统的sysfs中,你可以通过驱动A关联的class或总线名称,查找对应的设备是否存在且已完成绑定:
#include <linux/device.h> #include <linux/class.h> // 检查驱动A是否已探测成功 static int drvA_is_probed(void) { struct class *target_cls; struct device *found_dev; // 替换为驱动A所属的class名称(比如"i2c-dev"、"gpio"或自定义class) target_cls = class_find(THIS_MODULE, "drvA_class"); if (!target_cls) return -EINVAL; // 替换为驱动A注册的设备名称 found_dev = class_find_device(target_cls, NULL, "drvA_device", device_match_name); class_put(target_cls); if (found_dev) { put_device(found_dev); return 0; // 驱动A已完成探测 } return -ENODEV; // 未探测或失败 } // 驱动B中需要触发的函数 void drvB_run_target_func(void) { if (!drvA_is_probed()) { pr_info("Driver A probed successfully, executing B's function\n"); // 这里写驱动B的业务逻辑 } else { pr_warn("Driver A not ready, skip B's function\n"); } }
如果驱动A没有自定义class,也可以用总线类型(比如platform、i2c)调用bus_find_device来查找。
方案二:针对Platform驱动的专属检查
如果驱动A是platform类型的驱动,可直接通过platform总线查询设备与驱动的绑定状态:
#include <linux/platform_device.h> static int drvA_platform_is_probed(void) { struct platform_device *pdev; // 替换为驱动A绑定的platform设备名称 pdev = platform_device_find("drvA_platform_dev", NULL); if (!pdev) return -ENODEV; // 检查设备是否已与驱动绑定 bool probed = (pdev->driver != NULL); put_device(&pdev->dev); return probed ? 0 : -ENODEV; }
方案三:自定义同步标志(最可靠的方式)
如果上述依赖系统总线的方式存在延迟或不确定性,可在驱动A中添加同步标志,直接告知驱动B自身状态:
驱动A侧(需导出符号)
#include <linux/completion.h> #include <linux/module.h> // 定义全局探测完成标志和完成量 static bool drvA_probed_flag = false; DECLARE_COMPLETION(drvA_probe_done); // 驱动A的probe函数 static int drvA_probe(struct platform_device *pdev) { // 驱动A的探测逻辑 // ... // 标记探测完成 drvA_probed_flag = true; complete(&drvA_probe_done); return 0; } // 导出符号供驱动B访问 EXPORT_SYMBOL_GPL(drvA_probed_flag); EXPORT_SYMBOL_GPL(drvA_probe_done);
驱动B侧
// 引用驱动A导出的符号 extern bool drvA_probed_flag; extern struct completion drvA_probe_done; void drvB_run_target_func(void) { // 非阻塞检查:直接判断标志位 if (drvA_probed_flag) { // 执行驱动B的逻辑 } // 阻塞等待(如果需要等驱动A完成探测再执行) // wait_for_completion_timeout(&drvA_probe_done, msecs_to_jiffies(2000)); // if (drvA_probed_flag) { // // 执行逻辑 // } }
方案对比
- 方案一/二无需修改驱动A,但依赖驱动A的设备注册信息,可能存在系统同步延迟;
- 方案三最直接可靠,但需要修改驱动A代码,且要注意模块加载顺序(确保驱动A先于B加载,或B处理依赖)。
内容的提问来源于stack exchange,提问作者fmuller1
相关产品推荐
相关产品推荐

