一句话概括
这篇文章讲解Android 系统中跨进程通信(Binder机制)在 C++ 层的实现原理,主要拆解了三个关键角色:协议类(菜单)、服务端(厨师)、客户端(顾客)。
形象比喻
想象一家餐厅的运作:
- 协议类(IHelloService):就像一份菜单,定义了"打招呼"和"向某人打招呼"两个服务项目
- 服务端(BnHelloService):后厨的厨师,真正实现做菜(具体业务逻辑)
- 客户端(BpHelloService):餐厅前台的接单员,负责把顾客需求转达给后厨
- Binder驱动:相当于传菜员,负责在厨师和接单员之间传递信息
核心组件详解
1. 协议类(菜单)
cpp
Copy
class IHelloService: public IInterface {
virtual void sayHello() = 0; // 定义打招呼服务
virtual int sayHelloTo(name) = 0; // 定义带参数的打招呼服务
};
-
作用:定义服务接口(就像菜单列出的菜品)
-
特点:
- 继承自
IInterface,具备转换为Binder对象的能力 - 使用
DECLARE_META_INTERFACE宏生成辅助代码,方便接口转换
- 继承自
2. 服务端实现(厨师)
cpp
Copy
class BnHelloService: public BnInterface<IHelloService> {
status_t onTransact(...) { // 处理来自客户的请求
switch(请求类型) {
case 打招呼: 执行sayHello();
case 带参数打招呼: 执行sayHelloTo(name);
}
}
// 实际业务实现
void sayHello() { ALOGI("Hello!"); }
};
-
继承结构:
BnInterface:组合了协议接口和Binder基础功能BBinder:本地Binder对象,处理跨进程请求的基类
-
关键方法:
onTransact:收到请求时的处理中心(类似厨师的做菜流程)- 实际服务方法:真正执行业务逻辑的地方
3. 客户端代理(接单员)
cpp
Copy
class BpHelloService: public BpInterface<IHelloService> {
void sayHello() {
打包数据->通过BpBinder发送请求->接收结果
}
};
-
核心组成:
BpInterface:组合协议接口和代理功能BpRefBase:持有BpBinder(实际通信工具)
-
工作流程:
- 将方法调用打包成数据包(Parcel)
- 通过
BpBinder发送给服务端 - 接收返回结果并解析
核心类关系图
客户端 服务端
BpHelloService -> BpBinder ------> BBinder <- BnHelloService
↑ ↑
└── 共用协议接口 IHelloService ──┘
工作流程示例(以打招呼为例)
-
客户端调用:
cpp Copy helloService->sayHello(); -
数据打包:将方法名、参数打包成Parcel数据包
-
跨进程发送:通过BpBinder发送请求码(HELLO_SVR_CMD_SAYHELLO)
-
服务端处理:
- Binder驱动将请求路由到正确的BBinder
- 触发onTransact方法,解析请求码
- 调用真正的sayHello()实现
-
结果返回:将执行结果打包返回客户端
关键设计思想
- 接口与实现分离:通过协议接口实现客户端/服务端解耦
- 代理模式:客户端通过代理对象访问远程服务
- 数据序列化:使用Parcel进行数据打包/解包
- 请求路由:通过transaction code区分不同服务方法
这种设计使得Android系统可以优雅地实现跨进程通信,开发者只需要关注业务逻辑的实现,复杂的通信细节都由Binder框架自动处理。