4.7 KiB
4.7 KiB
Binder机制
目录
Binder原理
Binder 简介
// Binder:Android 的进程间通信(IPC)机制
// - 基于 Linux 内核的驱动
// - 高性能
// - 安全性好
// - 一次拷贝
为什么使用 Binder?
// 1. 性能:一次拷贝,比 Socket 快
// 2. 安全:基于 UID/PID 的身份验证
// 3. 易用:面向对象的接口
// 4. 稳定:内核驱动,稳定性好
Binder架构
架构图
┌─────────────┐
│ Client │ ←─── 客户端进程
└──────┬──────┘
│
┌──────▼──────┐
│ Proxy │ ←─── 代理对象
└──────┬──────┘
│
┌──────▼──────┐
│ Binder │ ←─── Binder 驱动
└──────┬──────┘
│
┌──────▼──────┐
│ Stub │ ←─── 存根对象
└──────┬──────┘
│
┌──────▼──────┐
│ Service │ ←─── 服务端进程
└─────────────┘
核心组件
// 1. Binder 驱动:Linux 内核模块
// 2. ServiceManager:管理所有服务
// 3. Binder 代理:客户端代理对象
// 4. Binder 实体:服务端真实对象
Binder通信流程
通信流程
1. Client 调用 Proxy 方法
2. Proxy 将数据打包(Parcel)
3. 通过 Binder 驱动发送到 Service
4. Service 的 Stub 接收数据
5. Stub 解包数据,调用真实方法
6. 返回结果,反向传输
数据传递
// Binder 使用 Parcel 传递数据
// Parcel:轻量级序列化机制
Parcel parcel = Parcel.obtain();
parcel.writeString("Hello");
parcel.writeInt(123);
parcel.setDataPosition(0);
String str = parcel.readString();
int num = parcel.readInt();
parcel.recycle();
AIDL
AIDL 定义
// AIDL:Android Interface Definition Language
// 用于定义跨进程接口
// IMyService.aidl
interface IMyService {
int add(int a, int b);
void setData(String data);
}
AIDL 使用
// 服务端实现
public class MyService extends Service {
private IMyService.Stub binder = new IMyService.Stub() {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public void setData(String data) {
// 处理数据
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
// 客户端使用
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyService myService = IMyService.Stub.asInterface(service);
int result = myService.add(1, 2);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Binder性能
性能优势
// 1. 一次拷贝:数据只拷贝一次
// 2. 内存映射:使用 mmap
// 3. 内核优化:内核驱动优化
性能对比
// Binder vs 其他 IPC
// - Socket:两次拷贝,性能差
// - 管道:两次拷贝,性能差
// - 共享内存:需要同步,复杂
// - Binder:一次拷贝,性能好
Binder源码分析
关键类
// IBinder:Binder 接口
// Binder:Binder 基类
// BinderProxy:Binder 代理
// Parcel:数据容器
关键流程
// 1. 服务注册:ServiceManager.addService()
// 2. 服务获取:ServiceManager.getService()
// 3. 数据传递:通过 Binder 驱动
// 4. 方法调用:Proxy → Stub
面试常见问题
Q1: Binder 的原理?
答案:
- 基于 Linux 内核的驱动
- 使用内存映射(mmap)实现一次拷贝
- 通过 Binder 驱动实现进程间通信
Q2: 为什么 Android 使用 Binder?
答案:
- 性能好:一次拷贝
- 安全性:基于 UID/PID 验证
- 易用性:面向对象接口
- 稳定性:内核驱动
Q3: Binder 通信流程?
答案:
- Client 调用 Proxy
- Proxy 打包数据
- 通过 Binder 驱动发送
- Service 的 Stub 接收
- Stub 调用真实方法
- 返回结果
Q4: AIDL 的作用?
答案:
- 定义跨进程接口
- 自动生成 Proxy 和 Stub
- 简化 Binder 使用
最后更新:2024年