Linux内核驱动A能否获取自身绑定设备并导出API供驱动B调用?
结论:驱动A完全可以获取所有已完成探测并绑定到自身的设备
Linux内核的统一设备驱动模型原生提供了对应的机制,无需自己额外维护绑定设备列表,具体实现方案如下:
实现核心逻辑
内核中每个struct device_driver实例(即每个驱动对应的内核结构)都会自动维护已经绑定到该驱动的设备链表,你可以直接用内核封装好的遍历接口操作,不需要手动管理链表。
驱动A的具体实现步骤
- 定义要导出的API,使用内核标准的符号导出宏对外暴露接口,GPL协议驱动建议用
EXPORT_SYMBOL_GPL,非GPL驱动可用EXPORT_SYMBOL - API内部调用内核提供的
driver_for_each_device辅助函数遍历所有绑定到自身的设备,该函数会自动持有驱动模型的锁保证遍历安全 - 自行实现遍历回调函数,将需要返回的设备信息存入传入的列表结构,注意调用
get_device()给设备引用计数加1,避免设备被解绑时结构被提前释放
代码示例(驱动A侧)
#include <linux/device.h> #include <linux/list.h> #include <linux/mutex.h> #include <linux/module.h> /* 自定义的返回设备信息结构,可按需扩展字段 */ struct a_bound_dev { struct device *dev; struct list_head entry; }; /* 驱动自身的互斥锁,保护遍历和列表操作 */ static DEFINE_MUTEX(a_drv_mutex); /* 驱动A自身的device_driver实例,实际使用时替换为你自己的驱动对象 */ extern struct device_driver a_driver; static int __collect_dev_cb(struct device *dev, void *data) { struct list_head *out_list = data; struct a_bound_dev *dev_node; dev_node = kzalloc(sizeof(*dev_node), GFP_KERNEL); if (!dev_node) return -ENOMEM; /* 增加设备引用计数,避免后续设备解绑时结构被释放 */ dev_node->dev = get_device(dev); list_add_tail(&dev_node->entry, out_list); return 0; } /** * a_get_bound_devs - 导出给其他驱动的API,获取驱动A所有绑定的设备 * @out_list: 调用方传入的链表头,返回的设备信息会挂在这个链表上 * 返回值:0为成功,负数为错误码 * 注意:调用方用完列表后需要遍历每个节点调用put_device(),再释放节点内存 */ int a_get_bound_devs(struct list_head *out_list) { int ret; if (!out_list) return -EINVAL; mutex_lock(&a_drv_mutex); ret = driver_for_each_device(&a_driver, NULL, out_list, __collect_dev_cb); mutex_unlock(&a_drv_mutex); return ret; } EXPORT_SYMBOL_GPL(a_get_bound_devs);
注意事项
- 驱动B调用API拿到设备列表后,必须在使用完每个设备后调用
put_device()释放引用,否则会出现内存泄漏或者use-after-free问题 - 如果驱动A支持动态卸载,需要确保驱动卸载时所有导出API的调用都已结束,可通过驱动依赖声明或者引用计数机制保证
内容的提问来源于stack exchange,提问作者VIPPER
相关产品推荐
相关产品推荐

