Binder 系列导读:九篇文章应该怎样读?

10 阅读7分钟

Binder 系列导读:九篇文章应该怎样读?

Binder 难读,不是因为缺一张更大的调用链图,而是因为 Java 方法、协议、远端引用、驱动对象和线程等待经常被压成一句“走 Binder”。这九篇沿同一笔调用逐层拆开:先看它怎样跨进程,再追协议、对象、驱动、服务发现和线程,最后用身份、死亡通知与一次慢调用检验这套模型是否真的能用于工程现场。

不必按函数名背源码。第一次读到能说清每一层“拿到什么、交给谁、何时算完成”即可;遇到具体问题,再回到对应篇目的源码坐标和证据段落。

讨论范围固定为 Framework Java AIDL + /dev/binder。NDK / Rust 后端、hwbindervndbinder 与 Stable AIDL 只在需要划边界时出现,不与这条主调用链混写。

一、四条阅读路线

路线 0:15 分钟最短路径

这条路线按小节而不是按整篇阅读,先得到一个可用模型:

  1. 导读第五节“核心术语表”
  2. 第一篇:跨进程总图
  3. 第二篇:IInterface 与 IBinder
  4. 第三篇:三层对象映射图
  5. 第五篇:注册与查询双时序图
  6. 第六篇:四种基本执行模型

读完先能区分 Proxy / Stub、handle / node、服务发现、Binder 线程 / Handler 和同步 / oneway;函数级源码第二遍再追。

路线 A:第一次建立 Binder 模型

按下面顺序阅读每篇的调用图、对象表和主链总结,函数级分支暂时跳过:

一:跨进程调用地图
→ 二:AIDL 协议
→ 三:远端对象引用
→ 四:`BC_TRANSACTION` 到 `BR_TRANSACTION`
→ 五:服务发现
→ 六:线程与完成语义

读完应能回答:

谁把方法编码成事务?
谁代表远端对象?
驱动怎样知道送到哪里?
服务端哪条线程执行?
同步返回、oneway 返回和 Handler 完成分别意味着什么?

路线 B:Android 系统源码下钻

一:Java → JNI → libbinder 总入口
→ 三:BinderProxy / BpBinder / binder_ref / binder_node
→ 四:binder_transaction() 路由与对象转换
→ 五:handle 0 与 servicemanager
→ 六:Binder 线程池、嵌套事务和重入
→ 七:calling identity
→ 八:死亡通知

路线 C:故障定位

六:线程、Handler、重入与死锁
→ 七:身份是否在转线程后丢失
→ 八:远端死亡和重连竞态
→ 九:线程栈、Binder flow、日志与 dumpsys 证据链

二、每篇只拆一层

同一个概念只在最相关的篇目里完整解释;其他篇只引用结论,不重新铺一遍定义。这样顺序读不会反复,单篇查问题也能找到明确入口。

篇目这一篇拆什么读完应抓住什么
一次同步 Java 方法怎样跨进程执行并返回三条边界、两端入口线程、reply
AIDL 怎样生成双方对称的协议胶水Proxy、Stub、Parcel、descriptor、code
本地 BinderProxy 怎样代表远端 Binder 端点Java / Native / Kernel 对象关系
驱动怎样实际路由和转换一笔事务target 语义、队列、buffer、对象转换
客户端第一次怎样通过名字获得 Binder 引用注册、查询、handle 0 的 context 范围
谁执行事务,同步、oneway、Handler 和重入怎样关联完成语义与并发矩阵
服务端怎样读取直接调用者身份直接发送方、线程切换、clear/restore
远端死亡怎样变成客户端通知linkToDeath 竞态、generation、恢复边界
一次调用慢或失败时怎样建立可验证 RCA不重叠时间片和证据三角形

三、贯穿系列的 BinderLab 接口

BinderLab AIDL 目录提供完整可构建协议;正文只摘取每篇需要的方法。延迟、oneway、callback 实验使用 requestId 关联事件,死亡实验另用 connectionEpoch / generationId 区分连接代次。

方法第一次承担主线的文章
add()第一篇:同步调用总图
addWithRequestId()第九篇:Binder 入口等待 Handler 的可关联延迟实验
AIDL 生成协议第二篇
registerCallback() / IResultCallback第三篇:异步 callback、角色反转和 Binder 引用传播
notifyValue()第六篇:Binder 入口内的 oneway 串行
getAsyncWorker() / IAsyncWorker第六篇:同 node 串行与不同 node 可并发的对照
notifyValueViaHandler()第六篇:Binder 转 Handler 后的异步 callback
addAndCallback() / ISyncResultCallback第六篇:同步嵌套事务与等待线程复用

四、系列统一基线

除非单篇明确标出其他参考,九篇正文和 BinderLab 使用同一组读者口径:

维度统一值
Framework / JNI / libbinder / servicemanagerandroid-16.0.0_r4,Android 16 QPR2
Binder DriverAndroid Common Kernel android16-6.12-2025-12_r1,commit 67fe3c9d
compile SDKAndroid SDK Platform 36.1
targetSdk36
minSdk26;这是 APK 声明的最低安装 API,证据包不包含 API 26 运行或行为验证
Build Tools / AIDL36.0.0
真机证据Android 16 / API 36
BinderLab 发布android16-qpr2-evidence-v1.3

五、核心术语表

术语稳定含义不要理解成
AIDL 业务 Proxy提供类型化业务方法并按协议写 ParcelJava BinderProxy
BinderProxyJava 层通用远端 IBinder 代理服务端对象地址
BpBinderNative 层远端 Binder 代理Java 业务接口
handle某个引用持有进程查找 binder_ref 的编号全系统唯一对象 ID
binder_ref某个进程对远端 node 的驱动引用远端 Java 对象
binder_node本地 Binder 端点在驱动中的表示直接持有 Java/C++ 指针的对象
Stub接收 code、解码 Parcel 并分发本地实现固定运行在主线程的对象
descriptor标识接口协议服务名或 handle
transaction code标识接口中的方法全局方法 ID
ServiceManager通过名字发现根 Binder 引用所有业务调用的中转站
handle 0当前 Binder context 的 context manager 入口/dev/binderhwbindervndbinder 的全局唯一对象
同步事务调用方等待服务端方法返回和 reply服务所有内部异步工作都完成
oneway调用方不等待业务 reply新建线程、并行执行或保证成功
calling UID当前事务的直接发送方 UID多跳调用自动透传的原始业务发起者
DeathRecipient旧远端 Binder 失效通知保活或自动重连

七、文章导航

  1. 一次方法调用,究竟怎样跨进程执行?
  2. AIDL 生成的 Proxy、Stub 和 Parcel 到底在做什么?
  3. BinderProxy 到底指向远端什么对象?
  4. ioctl 之后,事务怎样到达目标进程?
  5. ServiceManager 怎样把服务名变成可调用的 Binder?
  6. 服务端方法到底在哪条线程执行?
  7. getCallingUid() 读到的是谁?
  8. 远端进程死了,BinderProxy 为什么还能收到通知?
  9. 一次调用变慢,到底卡在哪里?