Binder通信机制测试验证与性能调优入门学习 - 第3节
3.1 Binder协议概述
Binder协议是Android系统中用于实现跨进程通信(IPC)的核心协议。它基于C/S(客户端/服务器)架构,通过共享内存与内核驱动的协同工作,实现了高效、安全的数据传输。Binder协议定义了通信双方的数据格式、交互流程以及状态转换规则,是理解Binder通信机制的基础。
核心特点:
- 面向对象:Binder通信以Binder对象为基本单元,客户端通过代理对象调用服务端方法。
- 一次拷贝:与传统IPC(如Socket、管道)的两次拷贝不同,Binder利用内核空间与用户空间的内存映射,实现一次数据拷贝。
- 安全性:Binder协议内置UID/PID校验,确保通信双方的身份可信。
3.2 BC与BR协议
Binder协议的核心交互由两组命令构成:BC(Binder Command)和BR(Binder Return)。BC命令由用户空间发送给Binder驱动,BR命令由Binder驱动返回给用户空间。两者共同构成了Binder通信的“指令集”。
3.2.1 BC命令(客户端→驱动)
BC命令用于客户端向Binder驱动发起操作请求,常见的BC命令包括:
| 命令码 | 含义 | 数据格式 |
|---|---|---|
BC_TRANSACTION |
发起一次Binder事务(调用服务端方法) | binder_transaction_data |
BC_REPLY |
服务端回复事务结果 | binder_transaction_data |
BC_ACQUIRE |
增加Binder对象的引用计数 | int32_t (Binder句柄) |
BC_RELEASE |
减少Binder对象的引用计数 | int32_t (Binder句柄) |
BC_FREE_BUFFER |
释放驱动分配的缓冲区 | void* (缓冲区地址) |
3.2.2 BR命令(驱动→用户空间)
BR命令是Binder驱动对用户空间请求的响应或主动通知:
| 命令码 | 含义 | 触发场景 |
|---|---|---|
BR_TRANSACTION |
通知服务端有新的请求到达 | 客户端发起BC_TRANSACTION后 |
BR_REPLY |
通知客户端服务端已回复 | 服务端发起BC_REPLY后 |
BR_DEAD_BINDER |
通知客户端Binder服务端已死亡 | 服务端进程异常退出 |
BR_SPAWN_LOOPER |
驱动要求用户空间创建新线程处理请求 | 当前线程池已满 |
BR_NOOP |
空操作,用于唤醒线程 | 驱动内部调度 |
提示:BC命令和BR命令通过
ioctl()系统调用传递,数据封装在binder_write_read结构体中。驱动通过解析命令码决定后续行为。
3.3 Binder通信的四个核心步骤
一次完整的Binder通信过程可以拆解为四个核心步骤:注册服务、获取服务、发起事务、处理事务。这四个步骤构成了Binder通信的完整生命周期。
3.3.1 步骤一:注册服务(Service Registration)
服务端进程向Service Manager(服务管理器)注册其Binder服务,使得客户端能够通过服务名查找到该服务。
- 操作:服务端调用
ServiceManager.addService()(Java层)或defaultServiceManager()->addService()(Native层)。 - 协议:服务端向Service Manager发送
BC_TRANSACTION,携带服务名和Binder引用。 - 结果:Service Manager将服务名与Binder句柄的映射关系存入内部哈希表。
3.3.2 步骤二:获取服务(Service Lookup)
客户端通过服务名向Service Manager查询目标服务的Binder代理。
- 操作:客户端调用
ServiceManager.getService()(Java层)或defaultServiceManager()->getService()(Native层)。 - 协议:客户端向Service Manager发送
BC_TRANSACTION,携带服务名。 - 结果:Service Manager返回目标服务的Binder句柄,客户端获得代理对象。
3.3.3 步骤三:发起事务(Transaction Initiation)
客户端通过代理对象向服务端发起方法调用请求。
- 操作:客户端调用代理对象的接口方法(如
transact())。 - 协议:客户端发送
BC_TRANSACTION,数据封装在binder_transaction_data中,包含方法ID、参数数据、Binder对象引用等。 - 驱动处理:Binder驱动将数据从客户端用户空间拷贝到内核空间,再映射到服务端用户空间(一次拷贝)。
3.3.4 步骤四:处理事务(Transaction Handling)
服务端接收并处理客户端的请求,然后返回结果。
- 操作:服务端线程池中的线程收到
BR_TRANSACTION,调用对应的服务方法。 - 协议:服务端处理完成后,发送
BC_REPLY,驱动转发BR_REPLY给客户端。 - 结果:客户端收到回复数据,完成一次同步Binder调用。
注意:如果服务端处理时间较长,客户端可以选择异步调用(oneway),此时服务端无需回复
BC_REPLY,驱动直接返回BR_TRANSACTION_COMPLETE。
3.4 Binder协议数据格式
Binder协议的数据传输以binder_transaction_data结构体为核心,该结构体定义了事务的元数据和载荷。
struct binder_transaction_data {
/* 通用字段 */
union {
__u32 handle; // 服务端Binder句柄(客户端使用)
void *ptr; // Binder对象指针(服务端使用)
} target;
void *cookie; // 服务端私有数据
__u32 code; // 方法ID(如 TRANSACTION_CALL)
/* 权限与标识 */
__u32 flags; // 标志位(如 TF_ONE_WAY)
pid_t sender_pid; // 发送方PID
uid_t sender_euid; // 发送方UID
/* 数据大小 */
__u32 data_size; // 数据区大小(字节)
__u32 offsets_size;// 偏移数组大小(用于Binder对象定位)
/* 数据载荷 */
union {
struct {
const void __user *buffer; // 数据缓冲区指针
const __u32 *offsets;// 偏移数组指针
} ptr;
__u8 buf[8]; // 小数据内联缓冲区
} data;
};
关键字段说明:
target.handle:客户端通过句柄标识目标服务端,句柄由Service Manager分配。code:方法ID,服务端根据此ID分发到具体方法。flags:标志位,TF_ONE_WAY表示异步调用,无需等待回复。data.ptr.buffer:指向实际数据的指针,数据通过共享内存映射实现零拷贝。offsets:偏移数组,用于在数据中定位Binder对象引用,驱动会据此更新句柄。
3.5 Binder协议与通信模型总结
| 概念 | 说明 | 关键点 |
|---|---|---|
| Binder协议 | 定义通信双方的数据格式和交互规则 | 基于C/S架构,一次拷贝,安全性高 |
| BC命令 | 用户空间发送给Binder驱动的指令 | BC_TRANSACTION、BC_REPLY、BC_ACQUIRE等 |
| BR命令 | Binder驱动返回给用户空间的指令 | BR_TRANSACTION、BR_REPLY、BR_DEAD_BINDER等 |
| 注册服务 | 服务端向Service Manager注册Binder服务 | addService(),存储服务名与句柄映射 |
| 获取服务 | 客户端向Service Manager查询服务 | getService(),返回Binder句柄 |
| 发起事务 | 客户端通过代理对象发送请求 | BC_TRANSACTION,驱动一次拷贝 |
| 处理事务 | 服务端处理请求并回复 | BR_TRANSACTION → 执行 → BC_REPLY |
学习建议:理解Binder协议的关键在于掌握BC/BR命令的配对关系以及四个核心步骤的时序。建议结合
adb shell dumpsys binder命令查看实际Binder通信的统计信息,加深对协议的理解。