Binder 驱动深读:节点、引用与生命周期
2026/8/9大约 3 分钟内核Android 14Binder 驱动内核生命周期
Binder 驱动深读:节点、引用与生命周期
上一章建立了内核全景。这一章回答:Binder 驱动在内核里维护什么,节点、引用、句柄 如何构成对象生命周期,binderfs 是什么?
句柄、引用与节点分属不同作用域
| 常见误解 | 正确理解 |
|---|---|
| Binder 驱动只转发数据 | 它还维护节点、引用与进程对象,管理对象生命周期 |
| 句柄就是地址 | 句柄是进程内对引用的编号,引用指向内核节点 |
| 进程退出后引用自动有效 | 驱动清理节点并触发死亡通知 |
核心结论
- 每个注册 Binder 的进程对应一个 binder_proc。
- 服务端对象对应 binder_node,客户端持有 binder_ref(句柄)。
- 引用计数决定节点何时清理,进程退出触发清理与死亡通知。
- binderfs 提供按需挂载的 Binder 设备(容器/虚拟化场景)。
- 泄漏与崩溃常与引用计数或节点清理错误相关。
内核对象主链
逐步解释:
- 句柄:客户端凭编号使用服务。
- 引用:ref 指向节点并计数。
- 节点:服务端对象实体。
- 进程:proc 是容器。
- 生命周期:计数归零或进程退出时清理。
为什么句柄不是地址
句柄只是进程内编号,真正的对象是 ref → node 映射。这样驱动可以安全地管理引用 计数、跨进程传递引用并防止地址泄露。这也是“不能伪造 getCallingUid”的内核基础。
源码证据
阅读目标:确认内核对象定义。
正文指针:drivers/android/binder.c 的 binder_proc/binder_node/binder_ref; drivers/android/binderfs.c 的 binderfs。
// drivers/android/binder.c(伪代码,行号以 r75 为准)
struct binder_node { ... }; // 服务端节点
struct binder_ref { ... }; // 客户端引用
struct binder_proc { ... }; // 进程上下文这段代码证明: 驱动维护完整对象模型;句柄、引用、节点的映射与引用计数是 Binder 生命周期管理的内核基础。
验证与排障
环境:root 设备或模拟器;内核调试节点需要 root。
adb shell su 0 cat /sys/kernel/debug/binder/proc/<pid>
adb shell su 0 cat /sys/kernel/debug/binder/transactions
adb shell su 0 ls /dev/binderfsbinder/proc/<pid> 看进程持有的引用与节点;transactions 看未完成事务。Binder 相关泄漏或异常先看内核对象状态,再回用户态日志。
常见误区
- “驱动只转发数据”:还管理对象生命周期。
- “句柄是地址”:是引用编号。
- “进程退出引用还在”:会清理并通知死亡。
- “binderfs 可有可无”:容器/虚拟化依赖它。
延伸问题
- 强引用与弱引用在内核中如何管理?
- 节点清理与死亡通知的时序是什么?
- binderfs 与 /dev/binder 的关系是什么?
- 引用泄漏会导致什么可见问题?
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
drivers/android/binder.c | 对象定义 | 生命周期 |
drivers/android/binderfs.c | 设备 | 容器 |
binder/proc/<pid> | 调试节点 | 排障 |
binder/transactions | 事务状态 | 排障 |
公共路径:drivers/android/。行号以 r75 检索为准。
进程与驱动共用的页管理基础,见 内核内存管理。