详细介绍:【底层机制】【Android】Binder架构与原理
Binder 架构与原理
一、Binder 整体架构
1. 架构组成
- Client:服务调用方
- Server:服务提供方
- ServiceManager:服务管理器,Android 系统启动时初始化的特殊 Binder 服务
- Binder 驱动:内核空间的核心组件,负责进程间通信
2. 通信模型
Client Process Kernel Space Server Process
| | |
| -- IBinder.Proxy ->| |
| | -- Binder Driver ->|
| | | -- IBinder.Stub
| | <- Transaction ---|
| <- Result --------| |
二、Binder 驱动核心机制
1. 内存映射(mmap)
// Binder 驱动关键数据结构
struct binder_proc {
struct hlist_node proc_node;
struct rb_root threads; // 线程红黑树
struct rb_root nodes; // Binder 节点
struct list_head delivered_death; // 死亡通知列表
};
struct binder_thread {
struct binder_proc *proc; // 所属进程
wait_queue_head_t wait; // 等待队列
struct binder_transaction *transaction_stack; // 事务栈
};
mmap 工作原理:
- 进程打开
/dev/binder设备后调用mmap() - Binder 驱动在内核空间分配缓冲区
- 同时映射到内核空间和用户空间
- 一次拷贝机制:数据从客户端用户空间拷贝到内核缓冲区,服务端直接读取
2. 数据传输流程
Client 发送数据:
- 数据打包为
binder_transaction_data - 通过
ioctl(BC_TRANSACTION)发送到驱动 - 驱动查找目标 Binder 实体
- 数据打包为
Server 接收数据:
- 服务线程通过
ioctl(BC_ENTER_LOOPER)进入循环 - 调用
ioctl(BINDER_WRITE_READ)读取事务 - 驱动唤醒等待的服务线程
- 服务线程通过
三、AIDL 本质解析
1. AIDL 生成的代码结构
// 自动生成的 Binder 接口
public interface IMyService extends android.os.IInterface {
// Binder 本地对象(服务端实现)
public static abstract class Stub extends android.os.Binder implements IMyService {
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) {
switch (code) {
case INTERFACE_TRANSACTION:
reply.writeString(DESCRIPTOR);
return true;
case TRANSACTION_doSomething:
data.enforceInterface(DESCRIPTOR);
int _arg0 = data.readInt();
String _result = this.doSomething(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
return super.onTransact(code, data, reply, flags);
}
}
// Binder 代理对象(客户端使用)
private static class Proxy implements IMyService {
private android.os.IBinder mRemote;
@Override
public String doSomething(int param) {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(param);
mRemote.transact(Stub.TRANSACTION_doSomething, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
}
2. AIDL 本质
- 代码生成工具:将接口定义转换为 Binder 通信代码
- Proxy-Stub 模式实现:
Proxy:客户端代理,序列化参数并调用transact()Stub:服务端基类,反序列化参数并调用实际方法
- 接口描述符机制:确保客户端和服务端接口版本一致
startActivity 的 Binder 调用全过程
一、进程内准备阶段
1. 发起调用
// Activity.java
public void startActivity(Intent intent) {
// 调用 ActivityTaskManager 服务
ActivityTaskManager.getService().startActivity(
mMainThread.getApplicationThread(),
mToken,
intent,
intent.resolveTypeIfNeeded(getContentResolver()),
null, // resultTo
null, // resultWho
0, // requestCode
FLAG_ACTIVITY_NEW_TASK,
null, // options
null // userId
);
}
二、Binder 调用链详细流程
1. 客户端到系统进程(第一次 Binder 调用)
Client Process (App) → System Server Process (AMS)
调用路径:
Activity.startActivity()ActivityTaskManager.getService().startActivity()IActivityTaskManager.Stub.Proxy.startActivity()
Binder 事务:
// IActivityTaskManager.aidl 生成的 Proxy 类
public int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, ...) {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
// ... 其他参数序列化
mRemote.transact(TRANSACTION_startActivity, data, reply, 0);
reply.readException();
int result = reply.readInt();
return result;
}
2. 系统进程处理(AMS 侧)
AMS 处理逻辑:
// ActivityTaskManagerService.java
public final int startActivity(IApplicationThread caller, ...) {
return getActivityStartController().obtainStarter(intent, ...)
.setCaller(caller)
.execute();
}
关键步骤:
- 权限验证:检查调用者权限
- Intent 解析:解析目标 Activity 信息
- 进程检查:判断目标 Activity 所在进程是否已启动
- 栈管理:确定 Activity 应该放入哪个 Task
3. 暂停当前 Activity(第二次 Binder 调用)
System Server Process (AMS) → Client Process (App)
AMS 调用应用进程:
// 通过 ApplicationThread 的 Binder 接口
app.thread.schedulePauseActivity(token, finished, userLeaving, configChanges);
应用进程处理:
// ActivityThread.java - ApplicationThread 内部类
public final void schedulePauseActivity(IBinder token, ...) {
sendMessage(H.PAUSE_ACTIVITY, token);
}
// H(Handler)处理消息
case PAUSE_ACTIVITY: {
handlePauseActivity((IBinder)msg.obj, ...);
break;
}
private void handlePauseActivity(IBinder token, ...) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
// 调用 Activity 的 onPause()
performPauseActivity(r, finished, reason, pendingActions);
}
}
4. 启动目标进程(如果需要)
进程创建流程:
- AMS 通过
Process.start()请求 Zygote - Zygote fork 新进程
- 新进程入口:
ActivityThread.main()
5. 启动目标 Activity(第三次 Binder 调用)
System Server Process (AMS) → Target Process (App)
AMS 调用目标进程:
// 通过目标进程的 ApplicationThread
thread.scheduleLaunchActivity(new Intent(r.intent), ...);
目标进程处理:
// ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, ...) {
// 1. 创建 Activity 实例
Activity activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
// 2. 创建 Application(如果不存在)
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
// 3. 关联 Context
activity.attach(appContext, ...);
// 4. 调用 onCreate()
mInstrumentation.callActivityOnCreate(activity, r.state);
// 5. 调用 onStart()
activity.performStart();
// 6. 调用 onResume()
activity.performResume();
}
三、Window 管理相关的 Binder 调用
1. 窗口创建(第四次 Binder 调用)
Target Process (App) → WindowManagerService (WMS)
调用流程:
// ActivityThread.handleResumeActivity()
final void handleResumeActivity(IBinder token, ...) {
// 调用 Activity.onResume()
ActivityClientRecord r = performResumeActivity(token, ...);
if (r.activity.mVisibleFromClient) {
// 添加窗口到 WMS
ViewManager wm = r.activity.getWindowManager();
wm.addView(decorView, layoutParams);
}
}
// WindowManagerGlobal.addView()
public void addView(View view, ViewGroup.LayoutParams params, ...) {
ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
root.setView(view, wparams, panelParentView);
}
ViewRootImpl 与 WMS 通信:
// ViewRootImpl.java
public void setView(View view, ...) {
// 通过 Session 与 WMS 通信
res = mWindowSession.addToDisplay(mWindow, ...);
}
四、Binder 驱动中的关键数据结构
1. 事务处理
struct binder_transaction_data {
union {
size_t handle; // 对 Server 的引用
void *ptr; // Server 的本地地址
} target;
void *data.ptr; // 数据缓冲区
size_t data_size; // 数据大小
};
// Binder 驱动处理事务
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr) {
// 查找目标 Binder 节点
target_node = binder_get_node(proc, tr->target.handle);
// 分配事务缓冲区
t = kzalloc(sizeof(*t), GFP_KERNEL);
// 拷贝数据到目标进程
t->buffer = binder_alloc_buf(target_proc, tr->data_size);
}
五、完整调用时序总结
[Client Process] [Binder Driver] [System Server] [Target Process]
| | | |
|--- startActivity() ------>| | |
| |-- TRANSACTION ------->| |
| | |-- AMS.startActivity() |
| | | |
| |<-- schedulePauseActivity --| |
|<-- onPause() ------------| | |
| | | |
| | |-- (如果需要)创建进程 -|
| | | |
| |<-- scheduleLaunchActivity -| |
| | | |-- onCreate()
| | | |-- onStart()
| | | |-- onResume()
| | | |-- addView()
| | | | (WMS调用)
六、性能优化关键点
- 一次拷贝优势:相比其他 IPC(如 Socket 需要 4 次拷贝),Binder 只需 1 次用户空间到内核空间的拷贝
- 引用计数:Binder 对象自动管理生命周期,避免内存泄漏
- 线程池管理:Binder 驱动维护线程池,避免频繁创建销毁线程
- 死亡通知:通过
linkToDeath()监控 Binder 服务状态,及时清理资源
整个 startActivity 过程涉及 3-4 次主要的 Binder 调用,通过精心设计的异步回调机制和状态管理,实现了跨进程的 Activity 启动流程。
浙公网安备 33010602011771号