Skip to content

Binder源码知识图谱

以 Binder 对象所有权、同步事务、线程、内存、安全和调试状态串联整个源码模块,并提供反向定位路径。

基于android-17.0.0_r1
AndroidBinder源码阅读

Binder源码知识图谱 ​

这是一篇导航与反向索引,不替代前文机制教材。正向阅读从服务发现走到事务释放;反向排查则从症状选择状态节点,再回到负责该状态的源码专题。下图只展示跨专题关系,具体算法仍回到对应文章。

本文是 Binder 模块的收束篇,面向已经读过 Binder调用源码地图 并完成至少一条 Native 或 Java 调用链的读者。它不重复 104 篇文章的摘要,而是把源码中的 owner、状态和消费者压缩为一套可反向使用的模型:看到 handle、pending transaction、caller UID、ENOSPC 或 timeout 时,应沿哪个对象回到哪段源码。

1. 五类Owner ​

Binder 的状态分别属于五类 owner:

Owner关键对象拥有什么
进程ProcessState、binder_procdriver fd、allocator、线程/节点/引用树、todo
线程IPCThreadState、binder_threadBC/BR buffer、calling identity、looper、transaction stack
对象BBinder/Binder、binder_node本地实现、最低调度策略、async queue、引用边沿
代理BpBinder/BinderProxy、binder_ref进程内 handle、死亡状态、目标 node 引用
事务Parcel、binder_transaction/buffercode、flags、payload、offsets、from/to、reply 与清理

先确定状态属于谁,再读调用链;否则容易把 binder_ref 当成全局句柄、把 maxThreads 当成实际线程数,或把 caller UID 当进程字段。

2. 服务发现 ​

  • frameworks/native/cmds/servicemanager/main.cpp
  • frameworks/native/cmds/servicemanager/ServiceManager.cpp
  • frameworks/native/libs/binder/IServiceManager.cpp
  • kernel/common/drivers/android/binder.c

ServiceManager 通过 BINDER_SET_CONTEXT_MGR 占据 context 的 handle 0。服务注册把本地 Binder node 交给 ServiceManager 的名称表;查询把该 node 转成调用进程的 binder_ref 和整数 handle。名称属于 ServiceManager,handle 属于客户端 proc,node 属于服务 proc。

对应专题:ServiceManager启动、addService注册服务、getService查询服务。

3. 代理形成 ​

源码文件:frameworks/native/libs/binder/ProcessState.cpp、frameworks/native/libs/binder/BpBinder.cpp

ProcessState::getStrongProxyForHandle 按 handle 复用 BpBinder;Java JNI 再映射为 BinderProxy。代理只是当前进程对远端 node 的引用视图:服务死亡后同一 BpBinder 进入 dead 状态,不会自动“复活”指向新进程。

对应专题:Binder代理生命周期、BpBinder代理对象、BinderProxy详解。

4. 数据协议 ​

源码文件:frameworks/native/libs/binder/Parcel.cpp、kernel/common/drivers/android/binder.c

Parcel payload 与 object offsets 共同定义事务:基本字段按对齐顺序读取,Binder/fd/PTR 对象由 offsets 定位,驱动转换为目标进程表示。接口 descriptor 只验证 Stub 协议;caller UID 来自驱动 credential;两者不可互换。

对应专题:Parcel读写契约、Binder对象编码、文件描述符传递。

5. 同步事务 ​

源码文件:frameworks/native/libs/binder/IPCThreadState.cpp、kernel/common/drivers/android/binder.c

cpp
writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
err = waitForResponse(reply);

驱动解析目标 ref/node,为目标 proc 分配 buffer,复制并 fixup 数据,入队并唤醒服务线程。服务线程收到 BR_TRANSACTION、调用 Stub/实现,再用 BC_REPLY 返回;原线程收到 BR_REPLY 后结束等待。BR_TRANSACTION_COMPLETE 只确认发送命令完成,不是业务 reply。

对应专题:Binder事务发送、同步调用阻塞模型。

6. 异步事务 ​

源码文件:kernel/common/drivers/android/binder.c

oneway 不保存同步 from/reply 栈,同一 node 通过 has_async_transaction + async_todo 串行;当前 buffer 释放后才推进下一项。不同 node 可以并行,发送成功不等于服务方法已执行成功。

对应专题:oneway异步接口、Binder异步队列。

7. 线程模型 ​

源码文件:frameworks/native/libs/binder/ProcessState.cpp、frameworks/native/libs/binder/IPCThreadState.cpp

startThreadPool 主动创建一个 PoolThread;驱动在无 waiter 且 started 小于 max 时返回 BR_SPAWN_LOOPER,用户态再创建并以 BC_REGISTER_LOOPER 注册。手动 joinThreadPool 是额外线程,maxThreads 不是总线程数。

对应专题:Binder线程池创建、Binder线程上限、Binder线程耗尽排查。

8. 嵌套与调度 ​

源码文件:kernel/common/drivers/android/binder.c

transaction_stack 用 from_parent/to_parent 维护嵌套同步关系,允许 B 回调 A 时复用 A 的等待线程。同步事务携带受支持的调用方调度策略;目标 node 的 min policy 和 inherit_rt 决定实际继承,reply 后按栈节点恢复。

对应专题:Binder嵌套调用、Binder优先级继承。

9. 内存路径 ​

源码文件:kernel/common/drivers/android/binder_alloc.c

目标 proc 的 binder allocator 用 best-fit 连续 buffer、按需装页和 async quota 管理 transaction。one-copy 是发送用户地址到目标 mapped buffer 的一次 copy,不是零拷贝;大数据应通过 Blob/Ashmem/memfd/MemoryHeapBase 传 fd 和元数据。

对应专题:Binder one-copy、binder_alloc_buf分配、Binder大数据传输。

10. 身份与安全 ​

源码文件:kernel/common/drivers/android/binder.c、kernel/common/security/selinux/hooks.c

驱动从 sender cred 生成 UID/PID/SID;Native 在入站事务期间设置线程 calling identity。framework permission、SELinux binder call/transfer/fd use、interface token 和业务 Binder token 是四个不同层次。clearCallingIdentity 只改变线程局部 caller 状态,不改变 Linux cred 或 SELinux transaction 判定。

对应专题:checkCallingPermission、SELinux与Binder、Binder Token机制。

11. 结束路径 ​

正常路径:reply 被读取,Parcel 释放后发送 BC_FREE_BUFFER;oneway 在 buffer 释放时推进 async queue。失败路径:目标死亡产生 BR_DEAD_REPLY,分配/对象/权限错误产生 BR_FAILED_REPLY,冻结同步调用产生 BR_FROZEN_REPLY。进程释放还会清理 thread、node、ref、death notification 和 allocator。

对应专题:事务数据生命周期、Binder死亡通知、TransactionTooLargeException。

12. 调试状态 ​

状态来源回答的问题
debugfs state/proc当前有哪些线程、node、ref、buffer、pending work
transaction log最近哪些事务成功/失败,debug id 与 errno 是什么
tracepoint/Perfetto时间花在排队、调度、服务、reply 还是释放
dumpsys服务自己认为什么状态,业务锁/队列是什么
线程栈/AVC/logcat用户锁、下游等待、权限和异常原因

对应专题:debugfs Binder节点、binder_transaction_log、Tracing Binder调用。

13. 源码图谱 ​

14. 反向索引 ​

  • 服务找不到:ServiceManager/context manager/name/ref。
  • 调用超时:线程栈、transaction stack、ready/pending、下游锁。
  • oneway 延迟:node async queue、buffer release、free async space。
  • FAILED_TRANSACTION:allocator、offset/fd fixup、SELinux、extended error。
  • 权限异常:caller identity、PermissionController、SELinux call/transfer。
  • 内存过大:Parcel size、largest free、Blob/fd 生命周期。
  • 性能尾延迟:transaction received、sched、service section、reply/release。

15. 阅读检查 ​

任选一次真实系统服务调用,从名称查找到 buffer 释放,逐项写出 owner、字段、源码文件和失败分支;再从一个现场症状反向选择三份证据和负责的专题。能在正向调用链与反向调试链之间切换,才算建立 Binder 源码模型。