probe、remove 与资源清理
这页讲的是:驱动不是匹配上设备就算结束,它还要在 probe 阶段把资源接起来,在 remove 阶段把现场收干净。学这页的重点,是理解驱动真正难的地方,常常不是“怎么开始工作”,而是“怎么安全进入、稳定存在、完整退出”。
这块是什么
probe、remove 与资源清理,讲的是驱动在和设备成功匹配之后,如何逐步把中断、内存映射、DMA、队列、后台工作等资源接入系统,又如何在设备离开、驱动卸载或错误回滚时,把这些关系安全撤掉。它是驱动生命周期里最容易体现系统工程味道的一段。
可以把 probe 理解成“正式接手现场并把设备布置妥当”,把 remove 理解成“有序撤场,确保没有线头还悬着”。
它负责什么
把设备真正接起来
- 匹配成功后完成初始化接管
- 建立中断、缓冲区、映射和回调关系
- 把硬件能力接入对应子系统
- 让设备从“被看见”变成“真的可用”
处理失败与回滚
- 不是每次 probe 都会顺利到底
- 中途失败时要收回已经拿到的资源
- 避免半初始化状态留在系统里
- 让失败不是随机烂尾,而是可控退出
有序退出与清理
- remove 时要停掉仍在运行的工作
- 解除绑定、释放资源、撤销关联
- 避免异步任务继续碰已失效对象
- 让设备离开或驱动卸载不留下后患
为什么 remove 常常比 probe 更难
| 原因 | 你现在怎么理解 | 为什么麻烦 |
|---|
| 系统里已经有很多关系 | probe 后驱动已和中断、内存、队列、子系统建立了联系。 | 退出时必须按正确次序逐步拆开。 |
| 异步工作可能还没结束 | 后台 work、超时、唤醒路径可能仍在飞。 | 如果清理太早,就容易碰到已失效对象。 |
| 资源不总是一步拿齐 | probe 常是分阶段拿资源、逐步接管。 | 失败回滚和最终 remove 都要知道已经走到哪一步。 |
| 退出时机往往更复杂 | 热插拔、错误恢复、模块卸载都可能触发 remove。 | 不是单一 happy path,而是多种场景下都要成立。 |
关键概念
| 概念 | 现在怎么理解 |
|---|
| probe | 驱动和设备匹配成功后,真正开始接管和初始化的入口。 |
| remove | 设备或驱动退出时,撤销接管并收回资源的入口。 |
| 资源清理 | 把中断、映射、缓冲区、异步工作等关系安全收掉。 |
| 回滚 | probe 中途失败时,把已经做过的部分撤回来。 |
| 悬空引用 | 对象明明已经清理了,别的路径却还想继续访问它。 |
为什么重要
- 它解释了为什么驱动代码经常显得不像“初始化一次就完”,而是充满成对出现的建立与释放动作。
- 很多最难查的驱动 bug,不在成功路径,而在失败回滚、热拔插和异步清理时序上。
- 理解这层后,你会更容易把模块生命周期、对象引用和后台工作联系起来。
- 它让你真正看见“系统级正确性”不只是启动成功,还包括退出也必须干净。
常见误解
- 误解一:probe 成功就说明驱动写得差不多了。实际上 remove 和回滚往往更考验质量。
- 误解二:资源释放只是善后细节。实际上清理顺序和时机常决定系统是否稳定。
- 误解三:只要设备不热拔插,就不用太在乎 remove。实际上模块卸载、错误恢复和失败路径都会碰到同类问题。
它不负责什么
- 它不替代总线匹配;匹配负责相遇,probe/remove 负责真正接管与撤场。
- 它不等于模块生命周期整体,但常是模块生命周期在驱动里的核心体现。
- 它不自动保证安全,反而是最容易暴露生命周期和并发问题的地方。
和其他模块的关系
| 相关模块 | 关系 |
|---|
| 总线、设备发现与驱动匹配 | 那页讲设备如何遇到驱动,这页细看遇到之后如何真正接手和撤离。 |
| 模块加载与生命周期 | 驱动模块装入后常会进入 probe,卸载前又常要经过 remove 与清理。 |
| workqueue / 定时器 | 退出时常要先停掉后台工作和超时路径,避免异步访问失效资源。 |
| DMA / 中断 / 内存映射 | 这些资源多半在 probe 阶段建立,并在 remove 阶段按顺序拆除。 |
读完这页后,你应该能回答
- 为什么驱动真正难的部分常常出现在 remove 和失败回滚?
- 为什么 probe 和 remove 需要成对地理解,而不是只看接管成功路径?
- 为什么异步工作和资源清理时序会让驱动问题显得格外棘手?
后面适合继续问:为什么很多驱动初始化代码像在一层层搭脚手架?remove 时最容易漏掉哪类后台关系?失败回滚和最终卸载的思路有什么共通之处?