设备驱动管理

发布时间:2026/8/25 5:03:14

设备驱动管理
设备驱动管理设备驱动管理覆盖从spi_driver注册、匹配、probe 到 remove 的完整生命周期。分五部分讲。一、struct spi_driver——设备驱动的结构体定义在spi.h:261~270struct spi_driver { const struct spi_device_id *id_table; // 匹配表 int (*probe)(struct spi_device *spi); // probe 回调 int (*remove)(struct spi_device *spi); // remove 回调 void (*shutdown)(struct spi_device *spi);// 关机回调 struct device_driver driver; // 嵌入通用驱动模型 };设备驱动开发者要做的事就是填这个结构体然后注册到内核。例如一个 SPI 触摸屏驱动static const struct spi_device_id my_touch_id[] { { edt-ft5406, 0 }, { } }; static struct spi_driver my_touch_driver { .driver { .name edt_ft5406, // 驱动名字 .of_match_table my_touch_of_match, // DT 匹配表 }, .id_table my_touch_id, // id_table 匹配表 .probe my_touch_probe, .remove my_touch_remove, }; module_spi_driver(my_touch_driver);二、注册——spi_register_driver开发者用module_spi_driver宏展开后实际调用的是spi_register_driver// spi.h:283 #define spi_register_driver(driver) \ __spi_register_driver(THIS_MODULE, driver) // spi.h:289 #define module_spi_driver(__spi_driver) \ module_driver(__spi_driver, spi_register_driver, spi_unregister_driver)module_driver宏展开为static int __init __spi_driver##_init(void) { return spi_register_driver((__spi_driver)); } static void __exit __spi_driver##_exit(void) { spi_unregister_driver((__spi_driver)); } module_init(__spi_driver##_init); module_exit(__spi_driver##_exit);所以一个module_spi_driver(my_touch_driver)替换了手写module_init和module_exit的模板代码。__spi_register_driverspi.c:389是关键int __spi_register_driver(struct module *owner, struct spi_driver *sdrv) { sdrv-driver.owner owner; sdrv-driver.bus spi_bus_type; // ↑ 告诉内核这个 driver 挂在 spi 总线上 if (sdrv-probe) sdrv-driver.probe spi_drv_probe; // 包装 probe if (sdrv-remove) sdrv-driver.remove spi_drv_remove; // 包装 remove if (sdrv-shutdown) sdrv-driver.shutdown spi_drv_shutdown; // 包装 shutdown return driver_register(sdrv-driver); // ↑ 注册到 driver core加入 spi_bus_type 的 driver 链表 }做了两件事把 SPI 驱动的回调包装成通用驱动的回调调driver_register注册到 driver core注册后 sysfs 中出现/sys/bus/spi/drivers/edt_ft5406/。三、匹配——spi_match_device当一个新的spi_device被device_add时driver core 遍历spi_bus_type上所有已注册的 driver调.match回调// spi.c:294 static int spi_match_device(struct device *dev, struct device_driver *drv) { const struct spi_device *spi to_spi_device(dev); const struct spi_driver *sdrv to_spi_driver(drv); // 1. DT compatible 匹配 if (of_driver_match_device(dev, drv)) return 1; // 2. ACPI 匹配 if (acpi_driver_match_device(dev, drv)) return 1; // 3. id_table 匹配 if (sdrv-id_table) return !!spi_match_id(sdrv-id_table, spi); // 4. name 回退匹配 return strcmp(spi-modalias, drv-name) 0; }spi_match_id逐一比较 id_table 中的 name 和spi-modaliasstatic const struct spi_device_id *spi_match_id( const struct spi_device_id *id, const struct spi_device *sdev) { while (id-name[0]) { if (!strcmp(sdev-modalias, id-name)) return id; id; } return NULL; }设备树中的信息流设备树 touch0 { compatible edt,edt-ft5406; }; ↓ of_modalias_node spi_device.modalis edt-ft5406 ↓ spi_match_device → of_driver_match_device spi_driver.of_match_table 中 compatible edt,edt-ft5406 → 匹配 ↓ 或走 id_table spi_driver.id_table 中 name edt-ft5406 → 匹配四、Probe——spi_drv_probe匹配成功后driver core 调sdrv-driver.probe(dev)也就是spi_drv_probe// spi.c:335 static int spi_drv_probe(struct device *dev) { const struct spi_driver *sdrv to_spi_driver(dev-driver); struct spi_device *spi to_spi_device(dev); int ret; // 1. 设置时钟 default ret of_clk_set_defaults(dev-of_node, false); if (ret) return ret; // 2. 从 DT 获取中断号 if (dev-of_node) { spi-irq of_irq_get(dev-of_node, 0); if (spi-irq -EPROBE_DEFER) return -EPROBE_DEFER; if (spi-irq 0) spi-irq 0; } // 3. 挂载电源管理域 ret dev_pm_domain_attach(dev, true); // 4. 调真正的设备驱动 probe if (ret ! -EPROBE_DEFER) { ret sdrv-probe(spi); if (ret) dev_pm_domain_detach(dev, true); } return ret; }设备驱动 probe 的标准写法static int my_touch_probe(struct spi_device *spi) { struct my_data *data; // 1. 设置设备参数如果 spi_add_device 的默认值不合适 spi-mode SPI_MODE_0; spi-max_speed_hz 1000000; spi_setup(spi); // ← 调 master-setup 配置硬件 // 2. 分配私有数据 data devm_kzalloc(spi-dev, sizeof(*data), GFP_KERNEL); >// spi.c:363 static int spi_drv_remove(struct device *dev) { const struct spi_driver *sdrv to_spi_driver(dev-driver); int ret; ret sdrv-remove(to_spi_device(dev)); dev_pm_domain_detach(dev, true); return ret; }设备驱动的 remove 做 probe 的逆操作释放中断、注销子系统、释放内存。六、Uevent——spi_uevent当设备被device_add时内核想发送一个 uevent 给用户态udev/mdev调.uevent回调// spi.c:313 static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) { const struct spi_device *spi to_spi_device(dev); // 优先 ACPI rc acpi_device_uevent_modalias(dev, env); if (rc ! -ENODEV) return rc; // 否则生成 MODALIASspi:xxx add_uevent_var(env, MODALIAS%s%s, SPI_MODULE_PREFIX, spi-modalias); return 0; }用户态收到的环境变量MODALIASspi:edt-ft5406。udev 据此自动加载驱动。七、完整生命周期图模块加载 │ ├─ module_spi_driver(my_driver) │ └─ module_init → spi_register_driver │ └─ driver_register(sdrv-driver) │ ├─ sdrv-driver.bus spi_bus_type │ └─ 加入 /sys/bus/spi/drivers/my_driver/ │ ├─ [已存在的 spi_device 触发匹配] │ └─ bus_probe_device │ └─ spi_match_device │ ├─ of_driver_match_device ← DT compatible │ ├─ acpi_driver_match_device │ ├─ spi_match_id(id_table) ← name 匹配 │ └─ strcmp(modalias, name) │ ├─ 匹配成功 │ └─ spi_drv_probe │ ├─ 获取 irq │ └─ sdrv-probe(spi) ← 设备驱动开始工作 │ ├─ spi_setup │ ├─ request_irq │ └─ 注册上层子系统 │ ├─ [正常工作] │ └─ spi_sync / spi_async / spi_write_then_read │ ├─ [模块卸载] │ └─ module_exit → spi_unregister_driver │ └─ driver_unregister │ └─ 调 sdrv-remove(spi) │ └─ 释放中断、注销子系统八、设备驱动的两种匹配方式总结匹配方式驱动中提供什么设备中提供什么匹配依据DT compatibledriver.of_match_tableDT 节点的compatibleedt,edt-ft5406字符串匹配id_tableid_table数组spi_device.modalismodalias字符串匹配name 回退driver.namespi_device.modalis字符串比较

相关新闻

大自然保护协会TNC全球人类改造v3(90米)数据集

大自然保护协会TNC全球人类改造v3(90米)数据集

2026/8/23 18:49:13

人类足迹的精确标尺:TNC全球人类改造v3(静态快照90米)数据集深度解读 引言 今天要解读的TNC全球人类改造v3(静态快照90米)数据集,则提供了一面映照人类活动在地球表面留下痕迹的镜子——它回答的是另一个…

LLM Weekly(2026.6.15-2026.6.21)

LLM Weekly(2026.6.15-2026.6.21)

2026/8/24 14:30:41

😎 网络新闻 SpaceX以600亿美元收购Cursor,达成AI领域首个重大退出交易。 SpaceX已提交具有约束力的合并协议,以价值600亿美元的股票收购Anysphere(Cursor),此次交易发生在其轰动一时的IPO后数日。Cursor的年经常性收入(ARR)已达到40亿美元。这笔交易标志着AI编程工具…

视觉定位概念_召回率_Top-K Recall,Loop Closure Recall(回环召回率),Localization Recall(定位召回率)

视觉定位概念_召回率_Top-K Recall,Loop Closure Recall(回环召回率),Localization Recall(定位召回率)

2026/8/23 7:13:53

在 SLAM(Simultaneous Localization and Mapping)、Visual Localization(视觉定位)、图像检索(Image Retrieval) 中,召回率(Recall) 是衡量有多少应该匹配成功的样本最终…

基于Codex与ChatGPT的金融数据自动化处理工具部署与测试指南

基于Codex与ChatGPT的金融数据自动化处理工具部署与测试指南

2026/8/25 4:54:47

这次我们来看一个名为“ChatGPT Work与Codex银行重置”的项目。根据标题和网络热词,这很可能是一个围绕OpenAI的Codex模型(或其衍生服务)和ChatGPT Work功能进行集成或重置的工具或服务。核心焦点在于“银行重置”,这可能意味着该…

可解释Transformer模型在临床预测任务中的部署与应用指南

可解释Transformer模型在临床预测任务中的部署与应用指南

2026/8/25 4:54:47

这次我们来看一个将Transformer模型应用于临床预测任务的开源项目。这个项目的核心目标不是简单地展示模型精度,而是解决一个更实际的问题:如何在结构化电子健康记录数据上,不仅做出准确的预测,还能让医生理解模型“为什么”做出这…

机器人跳舞背后的技术:从运动控制到具身智能的实践解析

机器人跳舞背后的技术:从运动控制到具身智能的实践解析

2026/8/25 4:54:47

你刷到过那个视频吗?——在某个科技展会上,一排人形机器人整齐划一地跳舞,动作流畅,甚至还有点“卡点”。很多人第一反应是“酷炫”,然后划走。但如果你停下来,把“机器人跳舞”这个现象,从一次…

企业级AI智能体规模化落地:从安全管控到可观测性的实战指南

企业级AI智能体规模化落地:从安全管控到可观测性的实战指南

2026/8/25 4:54:47

1. 从“玩具”到“武器”:企业级AI智能体的现实困境最近和几个技术VP聊天,大家普遍有个共识:现在做个AI智能体Demo,就像搭乐高一样简单。用LangChain、AutoGPT这类框架,配合OpenAI的API,一个下午就能搞出一…

GitHub Actions 自动修复失败构建,Codex 运维实战指南

GitHub Actions 自动修复失败构建,Codex 运维实战指南

2026/8/25 4:54:47

从“人工救火”到“自动愈合”:Codex 重构 CI/CD 故障处理流 在传统的 DevOps 工作流中,CI/CD 流水线变红往往是开发者最头疼的时刻。无论是凌晨三点的构建失败报警,还是复杂的依赖冲突导致的部署中断,团队通常需要经历“查看日志…

构建自托管、沙盒化、智能体驱动的软件工厂:架构蓝图与实践指南

构建自托管、沙盒化、智能体驱动的软件工厂:架构蓝图与实践指南

2026/8/25 4:44:47

如果你是一名开发者,最近一定被各种 AI 工具和“智能体”刷屏了。从 GitHub Copilot 到 Devin,从 AutoGPT 到各种 RAG 框架,似乎一夜之间,AI 就能接管所有开发工作。但兴奋过后,一个现实问题摆在眼前:这些工…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/24 19:53:32

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/24 19:56:07

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/24 21:16:09

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

2026/8/25 0:04:34

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory Meta Description:GetQzonehistory 是一个QQ空间历史说…

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

2026/8/25 0:04:35

【题目来源】 https://www.luogu.com.cn/problem/P7912 【题目描述】 小熊的水果店里摆放着一排 n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1,2,…,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里&#x…

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

2026/8/25 0:04:35

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG 【免费下载链接】transformers.js State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server! 项目地址: https:/…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/22 4:13:47

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/22 1:32:34

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…