Appearance
04_Binder 机制
核心摘要:Binder 是 Android 系统最核心的 IPC(进程间通信)机制,是理解 Android 系统架构的基石。AMS、PMS、WMS 等所有系统服务都通过 Binder 进行跨进程通信。
一、Binder 概述
1.1 什么是 Binder
Binder 是 Android 系统中一种轻量级的进程间通信(IPC)机制,由 Linux 内核驱动实现。它是 Android 系统最核心的通信基础设施,所有系统服务(AMS、PMS、WMS 等)都通过 Binder 进行跨进程通信。
核心特点:
- 高性能:只需一次数据拷贝(传统 IPC 需要两次)
- 安全性:支持身份验证和权限检查
- 易用性:基于 Client/Server 模型,接口清晰
- 跨语言:支持 Java、C++、Rust 等多种语言
1.2 Binder 的架构位置
┌─────────────────────────────────────────────────────────────┐
│ 应用层 (App) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Java Framework (AMS, PMS, WMS 等服务的 Java 代理) │ │
│ │ - IActivityManager.Stub.Proxy │ │
│ │ - IPackageManager.Stub.Proxy │ │
│ │ - IWindowManager.Stub.Proxy │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ JNI 层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ android_util_Binder.cpp │ │
│ │ - Java ↔ Native 桥梁 │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Native 层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ libbinder (C++ 框架层) │ │
│ │ - IBinder, IInterface, BnInterface, BpInterface │ │
│ │ - ProcessState, IPCThreadState │ │
│ └─────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Kernel 层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Binder 驱动 (/dev/binder) │ │
│ │ - 内存映射 (mmap) │ │
│ │ - 进程间数据传输 │ │
│ │ - 引用计数管理 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘1.3 Binder vs 传统 IPC
| 特性 | Binder | Socket | Pipe | MessageQueue |
|---|---|---|---|---|
| 性能 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 安全性 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
| 易用性 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| 跨进程 | ✅ | ✅ | ✅ | ❌ |
| 跨设备 | ❌ | ✅ | ❌ | ❌ |
| 身份验证 | ✅ | ❌ | ❌ | ❌ |
| 数据拷贝次数 | 1 次 | 2 次 | 2 次 | 0 次 |
为什么 Binder 只需要一次拷贝?
传统 IPC(两次拷贝):
┌──────────┐ 拷贝 1 ┌──────────┐ 拷贝 2 ┌──────────┐
│ 发送方 │ ────────────> │ 内核 │ ────────────> │ 接收方 │
│ 缓冲区 │ │ 缓冲区 │ │ 缓冲区 │
└──────────┘ └──────────┘ └──────────┘
Binder IPC(一次拷贝):
┌──────────┐ 拷贝 1 ┌──────────────────────────┐
│ 发送方 │ ────────────> │ 内核接收缓冲区 │
│ 缓冲区 │ │ (通过 mmap 映射到发送方) │
└──────────┘ └──────────────────────────┘
│
│ mmap 映射
▼
┌──────────────────────────┐
│ 接收方地址空间 │
│ (直接访问内核缓冲区) │
└──────────────────────────┘二、Binder 架构
2.1 整体架构图
┌─────────────────────────────────────────────────────────────┐
│ Binder 架构总览 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Client 进程 │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ BpBinder (Proxy) │ │ │
│ │ │ - 客户端代理 │ │ │
│ │ │ - 封装 IPC 调用 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ │ transact() │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ IPCThreadState │ │ │
│ │ │ - 线程本地状态 │ │ │
│ │ │ - 与 Binder 驱动通信 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ │ ioctl() │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ /dev/binder │ │ │
│ │ │ - Binder 驱动 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ │ 内核空间 │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Server 进程 │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ /dev/binder │ │ │
│ │ │ - Binder 驱动 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ ▲ │ │
│ │ │ ioctl() │ │
│ │ │ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ IPCThreadState │ │ │
│ │ │ - 线程本地状态 │ │ │
│ │ │ - 与 Binder 驱动通信 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ ▲ │ │
│ │ │ onTransact() │ │
│ │ │ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ BBinder (Stub) │ │ │
│ │ │ - 服务端实体 │ │ │
│ │ │ - 实现具体业务逻辑 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2.2 核心类层次结构
2.2.1 Native 层(C++)
┌─────────────────────────────────────────────────────────────┐
│ Native 层类层次结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ RefBase │
│ │ │
│ └─> LightRefBase<IBinder> │
│ │ │
│ └─> IBinder │
│ │ │
│ ├─> BpBinder (Proxy, 客户端) │
│ │ │
│ └─> BBinder (Stub, 服务端) │
│ │ │
│ └─> BnInterface<INTERFACE> │
│ │ │
│ └─> 具体 Service (如 BnAMs) │
│ │
│ IInterface │
│ │ │
│ └─> BpInterface<INTERFACE> (Proxy) │
│ │ │
│ └─> BnInterface<INTERFACE> (Stub) │
│ │
└─────────────────────────────────────────────────────────────┘核心类说明:
| 类 | 作用 | 位置 |
|---|---|---|
IBinder | Binder 接口基类 | Native |
BpBinder | Binder Proxy(客户端代理) | Native |
BBinder | Binder 实体(服务端) | Native |
BnInterface | Stub 基类模板 | Native |
BpInterface | Proxy 基类模板 | Native |
IInterface | 接口基类 | Native |
ProcessState | 进程状态管理 | Native |
IPCThreadState | 线程状态管理 | Native |
2.2.2 Java 层
┌─────────────────────────────────────────────────────────────┐
│ Java 层类层次结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ IBinder │
│ │ │
│ ├─> Binder (Stub 基类) │
│ │ │ │
│ │ └─> 具体 Service (如 ActivityManagerService) │
│ │ │
│ └─> BinderProxy (Proxy) │
│ │
│ IInterface │
│ │ │
│ └─> Stub (接口 Stub 基类) │
│ │ │
│ └─> Proxy (接口 Proxy 类) │
│ │
└─────────────────────────────────────────────────────────────┘2.3 Client/Server/ServiceManager 模型
┌─────────────────────────────────────────────────────────────┐
│ Client/Server/ServiceManager 模型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Client │ │ Server │ │
│ │ (App) │ │ (AMS/PMS) │ │
│ │ │ │ │ │
│ │ getService() │ publish() │ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ │ ▼ │ ▼ │ │
│ │ ┌─────────┐ │ ┌─────────┐ │
│ │ │ Proxy │ │ │ Stub │ │
│ │ └────┬────┘ │ └────┬────┘ │
│ │ │ │ │ │
│ │ │ transact() │ │ onTransact() │
│ │ ├─────────────────────┼───────┤ │
│ │ │ │ │ │
│ │ │ /dev/binder │ │ │
│ │ │ │ │ │
│ └───────┼─────────────────────┼───────┘ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Service │ │ │
│ └────│ Manager │◄────────────────────────────┘
│ │ (Native) │
│ └──────────────┘
│ │
│ │ addService() / getService()
│ │
│ ┌──────┴──────┐
│ │ 服务注册表 │
│ │ "activity" │
│ │ "package" │
│ │ "window" │
│ │ ... │
│ └─────────────┘
│ │
└─────────────────────────────────────────────────────────────┘三方角色:
| 角色 | 说明 | 示例 |
|---|---|---|
| Client | 服务调用者 | App 进程、其他系统服务 |
| Server | 服务提供者 | AMS、PMS、WMS |
| ServiceManager | 服务注册中心 | 管理所有 Binder 服务的注册和查询 |
三、Binder 驱动
3.1 驱动核心功能
Binder 驱动位于 Linux 内核空间,是 Binder IPC 的核心实现。
核心功能:
- 进程间数据传输:通过内存映射实现高效数据传输
- 线程管理:管理 Binder 线程池
- 引用计数:管理 Binder 对象的生命周期
- 权限检查:验证调用者 UID/PID
- 死亡通知:通知 Client 端 Server 端死亡
3.2 驱动数据结构
cpp
// drivers/android/binder.c
// Binder 进程上下文
struct binder_proc {
struct hlist_node proc_node; // 进程链表节点
struct rb_root threads; // 线程红黑树
struct rb_root nodes; // 节点红黑树
struct rb_root refs_by_desc; // 按描述符引用的红黑树
wait_queue_head_t wait; // 等待队列
struct binder_stats stats; // 统计信息
atomic_t tmp_ref; // 临时引用计数
bool is_dead; // 是否已死亡
struct task_struct *task; // 任务结构
};
// Binder 线程上下文
struct binder_thread {
struct binder_proc *proc; // 所属进程
struct rb_node rb_node; // 红黑树节点
unsigned pid; // 线程 PID
int looper; // 循环标志
struct binder_transaction *transaction_stack; // 事务栈
};
// Binder 节点(Server 端)
struct binder_node {
int debug_id;
struct binder_work work; // 工作项
union {
struct binder_work entry; // 入口工作项
struct list_head dead_node; // 死亡节点链表
};
struct binder_proc *proc; // 所属进程
struct hlist_node dead_node; // 死亡节点
void *ptr; // 本地指针
void *cookie; // Cookie
int has_strong_ref; // 强引用计数
int has_weak_ref; // 弱引用计数
};
// Binder 引用(Client 端)
struct binder_ref {
struct rb_node rb_node; // 按节点索引的红黑树
struct rb_node rb_node_desc; // 按描述符索引的红黑树
struct hlist_node node_entry; // 节点入口链表
struct binder_proc *proc; // 所属进程
struct binder_node *node; // 对应的节点
unsigned desc; // 描述符(句柄)
int strong; // 强引用计数
int weak; // 弱引用计数
};
// Binder 事务
struct binder_transaction {
int debug_id;
struct binder_work work; // 工作项
struct binder_transaction *from; // 源事务
struct binder_transaction_data data; // 事务数据
struct binder_proc *to_proc; // 目标进程
struct binder_thread *to_thread; // 目标线程
int to_node; // 目标节点
};3.3 驱动 IOCTL 命令
Binder 驱动通过 IOCTL 与用户空间通信。
cpp
// drivers/android/binder.c
// 主要 IOCTL 命令
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 2, __s64)
#define BINDER_SET_MAX_THREADS _IOW('b', 3, __u32)
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 4, __s32)
#define BINDER_SET_CONTEXT_MGR _IOW('b', 5, __s32)
#define BINDER_THREAD_EXIT _IOW('b', 6, __s32)
// BINDER_WRITE_READ 结构
struct binder_write_read {
__u64 write_size; // 写入数据大小
__u64 write_consumed; // 已消费数据大小
__u64 write_buffer; // 写入缓冲区指针
__u64 read_size; // 读取数据大小
__u64 read_consumed; // 已消费数据大小
__u64 read_buffer; // 读取缓冲区指针
};
// 事务数据
struct binder_transaction_data {
union {
binder_size_t handle; // 句柄(Client 端)
binder_uintptr_t ptr; // 指针(Server 端)
} target;
binder_uintptr_t cookie; // Cookie
__u32 code; // 事务代码
__u32 flags; // 标志
binder_pid_t sender_pid; // 发送者 PID
binder_uid_t sender_euid; // 发送者 UID
binder_size_t data_size; // 数据大小
binder_size_t offsets_size; // 偏移大小
union {
struct {
const void __user *buffer; // 数据缓冲区
const void __user *offsets; // 偏移缓冲区
} ptr;
__u8 buf[BINDER_LARGE_PAYLOAD]; // 内联数据
} data;
};3.4 内存映射机制
Binder 使用 mmap 实现内存映射,这是 Binder 高效的关键。
cpp
// drivers/android/binder.c
static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct binder_proc *proc = filp->private_data;
// 1. 检查映射大小
if (vma->vm_end - vma->vm_start > SZ_4M)
return -EINVAL;
// 2. 分配内核缓冲区
proc->buffer = dmam_alloc_coherent(proc->dev, size, &proc->buffer_phys, GFP_KERNEL);
// 3. 设置用户空间 VMA
vma->vm_pgoff = proc->buffer_phys >> PAGE_SHIFT;
// 4. 映射到用户空间
ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
size, vma->vm_page_prot);
// 5. 记录映射信息
proc->user_buffer_offset = vma->vm_start - proc->buffer_phys;
return ret;
}内存映射示意图:
┌─────────────────────────────────────────────────────────────┐
│ 内存映射示意图 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户空间 (User Space) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Client 进程地址空间 │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ mmap 区域 │ │ │
│ │ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │ │ 发送缓冲区 │ │ │ │
│ │ │ │ (写入数据) │ │ │ │
│ │ │ └─────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ │ 物理内存(内核缓冲区) │
│ │ ┌─────────────────────────────────────────────┐ │
│ │ │ 内核分配的连续物理内存 │ │
│ │ │ ┌─────────────────────────────────────┐ │ │
│ │ │ │ Binder 缓冲区 │ │ │
│ │ │ │ (Client 和 Server 共享) │ │ │
│ │ │ └─────────────────────────────────────┘ │ │
│ │ └─────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Server 进程地址空间 │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ mmap 区域 │ │ │
│ │ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │ │ 接收缓冲区 │ │ │ │
│ │ │ │ (直接访问内核缓冲区) │ │ │ │
│ │ │ └─────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 关键点: │
│ - Client 写入数据到 mmap 区域(拷贝 1 次) │
│ - Server 直接从 mmap 区域读取(零拷贝) │
│ - 内核维护物理内存,Client 和 Server 通过虚拟地址访问 │
│ │
└─────────────────────────────────────────────────────────────┘四、Binder 通信流程
4.1 完整通信流程
┌─────────────────────────────────────────────────────────────┐
│ Binder 通信完整流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Server 端注册服务 │
│ └─> ServiceManager.addService("activity", binder) │
│ │
│ 2. Client 端获取服务 │
│ └─> ServiceManager.getService("activity") │
│ │
│ 3. Client 端发起调用 │
│ └─> proxy.startActivity(intent) │
│ │
│ 4. 打包数据(Parcel) │
│ └─> Parcel.writeInterfaceToken() │
│ └─> Parcel.writeInt() / writeString() │
│ │
│ 5. 调用 transact() │
│ └─> binderProxy.transact(CODE, data, reply, flags) │
│ │
│ 6. JNI 层转换 │
│ └─> android_os_BinderProxy_transact() │
│ │
│ 7. Native 层调用 │
│ └─> BpBinder::transact() │
│ └─> IPCThreadState::transact() │
│ │
│ 8. 写入 Binder 驱动 │
│ └─> ioctl(BINDER_WRITE_READ) │
│ └─> 写入 BC_TRANSACTION 命令 │
│ │
│ 9. 内核处理事务 │
│ ├─> 查找目标节点 │
│ ├─> 创建 binder_transaction │
│ └─> 唤醒 Server 线程 │
│ │
│ 10. Server 端读取 │
│ └─> ioctl(BINDER_WRITE_READ) │
│ └─> 读取 BR_TRANSACTION 命令 │
│ │
│ 11. Server 端处理 │
│ └─> onTransact(CODE, data, reply, flags) │
│ └─> 执行具体业务逻辑 │
│ │
│ 12. 返回结果 │
│ └─> 反向流程,返回给 Client │
│ │
└─────────────────────────────────────────────────────────────┘4.2 Client 端源码分析
4.2.1 Java 层 Proxy
java
// frameworks/base/core/java/android/app/IActivityManager.java
public interface IActivityManager extends IInterface {
// 定义事务代码
int START_ACTIVITY_TRANSACTION = 1;
// 定义方法
int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
// Stub 抽象类
public abstract static class Stub extends Binder implements IActivityManager {
private static final String DESCRIPTOR = "android.app.IActivityManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static IActivityManager asInterface(IBinder obj) {
if (obj == null) return null;
// 本地接口
IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (iin != null && iin instanceof IActivityManager) {
return (IActivityManager) iin;
}
// 远程代理
return new IActivityManager.Stub.Proxy(obj);
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION: {
// 服务端处理
data.enforceInterface(DESCRIPTOR);
// ... 解析参数
int result = startActivity(caller, callingPackage, intent,
resolvedType, resultTo, resultWho, requestCode,
startFlags, profilerInfo, options);
reply.writeInt(result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
// Proxy 静态内部类
private static class Proxy implements IActivityManager {
private IBinder mRemote;
Proxy(IBinder remote) {
mRemote = remote;
}
@Override
public IBinder asBinder() {
return mRemote;
}
@Override
public int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
// 1. 创建请求 Parcel
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
// 2. 写入接口 Token
data.writeInterfaceToken(DESCRIPTOR);
// 3. 写入参数
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
if (intent != null) {
data.writeInt(1);
intent.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
// ... 写入其他参数
// 4. 调用 transact
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
// 5. 读取返回结果
reply.readException();
int result = reply.readInt();
return result;
} finally {
data.recycle();
reply.recycle();
}
}
}
}
}4.2.2 Native 层 BpBinder
cpp
// frameworks/native/libs/binder/BpBinder.cpp
status_t BpBinder::transact(unsigned code, const Parcel& data, Parcel* reply,
uint32_t flags)
{
// 1. 检查是否死亡
if (mAlive) {
status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = false;
return status;
}
return DEAD_OBJECT;
}4.2.3 IPCThreadState::transact()
cpp
// frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::transact(int target, uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
// 1. 写入数据到输出缓冲区
status_t err = writeTransactionData(BC_TRANSACTION, flags, target, 0, data, nullptr);
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return err;
}
// 2. 等待响应
if ((flags & TF_ONE_WAY) == 0) {
err = waitForResponse(reply);
}
return err;
}
status_t IPCThreadState::writeTransactionData(int cmd, uint32_t flags,
int target, int status, const Parcel& data, status_t* work)
{
// 1. 创建事务数据
binder_transaction_data tr;
tr.target.handle = target;
tr.cookie = 0;
tr.code = code;
tr.flags = flags;
tr.sender_pid = 0;
tr.sender_euid = 0;
tr.data_size = data.dataSize();
tr.offsets_size = data.objectsSize() * sizeof(binder_size_t);
tr.data.ptr.buffer = data.data();
tr.data.ptr.offsets = data.objects();
// 2. 写入命令
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
// 3. 写入数据
mOut.append(data.data(), data.dataSize());
return NO_ERROR;
}4.3 Server 端源码分析
4.3.1 加入线程池
cpp
// frameworks/native/libs/binder/ProcessState.cpp
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
class PoolThread : public Thread
{
protected:
bool threadLoop()
{
// 1. 加入 Binder 线程池
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
};4.3.2 加入线程池(Java 层)
java
// frameworks/base/core/java/android/os/Process.java
public static final void startThreadPool() {
// Native 方法
nativeStartThreadPool();
}cpp
// frameworks/base/core/jni/android_util_Binder.cpp
static void android_os_Process_nativeStartThreadPool(JNIEnv* env, jobject clazz)
{
android::ProcessState::self()->startThreadPool();
}4.3.3 处理事务
cpp
// frameworks/native/libs/binder/IPCThreadState.cpp
void IPCThreadState::joinThreadPool(bool isMain)
{
// 1. 注册到驱动
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
// 2. 进入循环
status_t result;
do {
// 3. 等待命令
result = getAndExecuteCommand();
// 4. 处理命令
if (result < NO_ERROR) break;
} while (result != -ECONNREFUSED && result != -EBADF);
// 5. 退出
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
// 1. 与驱动通信
result = talkWithDriver();
if (result >= NO_ERROR) {
// 2. 读取命令
uint32_t cmd = mIn.readInt32();
// 3. 执行命令
result = executeCommand(cmd);
}
return result;
}
status_t IPCThreadState::executeCommand(int cmd)
{
switch (cmd) {
case BR_TRANSACTION: {
// 处理事务
binder_transaction_data tr;
result = readFromParcel(&tr, sizeof(tr));
// 调用 onTransact
Parcel buffer;
buffer.ipcSetDataReference(tr.data.ptr.buffer, tr.data_size,
tr.data.ptr.offsets, tr.offsets_size / sizeof(binder_size_t),
freeBuffer, this);
const sp<BBinder> b = (const sp<BBinder>)tr.cookie;
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
// 发送响应
sendReply(reply, error);
break;
}
case BR_DEAD_BINDER: {
// 处理死亡通知
break;
}
}
return NO_ERROR;
}4.3.4 BBinder::transact()
cpp
// frameworks/native/libs/binder/Binder.cpp
status_t BBinder::transact(unsigned code, const Parcel& data, Parcel* reply,
uint32_t flags)
{
data.setDataPosition(0);
// 调用 onTransact
status_t err = onTransact(code, data, reply, flags);
if (reply != nullptr) {
reply->setDataPosition(0);
}
return err;
}五、Binder 内存映射详解
5.1 mmap 原理
┌─────────────────────────────────────────────────────────────┐
│ mmap 原理图解 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 虚拟地址空间 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Client 进程 │ │
│ │ 0x7f000000 ┌─────────────────────────────────┐ │ │
│ │ │ mmap 区域 │ │ │
│ │ │ (用户空间虚拟地址) │ │ │
│ │ │ ┌─────────────────────────┐ │ │ │
│ │ │ │ 发送缓冲区 │ │ │ │
│ │ │ │ (vma->vm_start) │ │ │ │
│ │ │ └─────────────────────────┘ │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ │ 页表映射 │
│ ▼ │
│ 物理内存 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 内核分配的连续物理内存 │ │
│ │ 0x10000000 ┌─────────────────────────────────┐ │ │
│ │ │ Binder 缓冲区 │ │ │
│ │ │ (物理地址) │ │ │
│ │ │ ┌─────────────────────────┐ │ │ │
│ │ │ │ 共享数据区 │ │ │ │
│ │ │ │ (proc->buffer) │ │ │ │
│ │ │ └─────────────────────────┘ │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ ▲ │
│ │ 页表映射 │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Server 进程 │ │
│ │ 0x7e000000 ┌─────────────────────────────────┐ │ │
│ │ │ mmap 区域 │ │ │
│ │ │ (用户空间虚拟地址) │ │ │
│ │ │ ┌─────────────────────────┐ │ │ │
│ │ │ │ 接收缓冲区 │ │ │ │
│ │ │ │ (vma->vm_start) │ │ │ │
│ │ │ └─────────────────────────┘ │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 数据流向: │
│ 1. Client 写入数据到自己的 mmap 区域(触发缺页中断) │
│ 2. 内核将数据复制到物理缓冲区(拷贝 1 次) │
│ 3. Server 从自己的 mmap 区域读取(直接访问物理缓冲区) │
│ │
└─────────────────────────────────────────────────────────────┘5.2 一次拷贝原理
为什么 Binder 只需要一次拷贝?
传统 IPC(Socket/Pipe):
┌──────────┐ copy_from_user ┌──────────┐ copy_to_user ┌──────────┐
│ 发送方 │ ──────────────────────> │ 内核 │ ──────────────────────> │ 接收方 │
│ 用户空间 │ │ 缓冲区 │ │ 用户空间 │
└──────────┘ └──────────┘ └──────────┘
│ │ │
│ 拷贝 1 │ 拷贝 2 │
▼ ▼ ▼
Binder IPC:
┌──────────┐ copy_from_user ┌──────────────────────────┐
│ 发送方 │ ──────────────────────> │ 内核物理缓冲区 │
│ 用户空间 │ │ (通过 mmap 映射) │
└──────────┘ └──────────────────────────┘
│
│ mmap 映射
│ (页表映射到接收方)
▼
┌──────────────────────────┐
│ 接收方用户空间 │
│ (直接访问物理缓冲区) │
└──────────────────────────┘
│
│ 零拷贝
▼
关键点:
- Client 的 mmap 区域和 Server 的 mmap 区域映射到同一块物理内存
- Client 写入时,数据从用户空间拷贝到物理内存(1 次)
- Server 读取时,直接访问物理内存(0 次)
- 总共 1 次拷贝六、Binder vs Socket vs Pipe
6.1 性能对比
| 指标 | Binder | Socket | Pipe |
|---|---|---|---|
| 数据拷贝 | 1 次 | 2 次 | 2 次 |
| 延迟 | 低 | 中 | 低 |
| 吞吐量 | 高 | 中 | 高 |
| 连接建立 | 快 | 慢 | 快 |
6.2 功能对比
| 功能 | Binder | Socket | Pipe |
|---|---|---|---|
| 跨进程 | ✅ | ✅ | ✅ |
| 跨设备 | ❌ | ✅ | ❌ |
| 身份验证 | ✅ | ❌ | ❌ |
| 权限检查 | ✅ | ❌ | ❌ |
| 死亡通知 | ✅ | ❌ | ❌ |
| 一对一 | ✅ | ✅ | ✅ |
| 一对多 | ✅ | ✅ | ❌ |
| 同步调用 | ✅ | ❌ | ❌ |
| 异步调用 | ✅ | ✅ | ✅ |
6.3 使用场景
| 场景 | 推荐 IPC | 理由 |
|---|---|---|
| Android 系统服务 | Binder | 内置支持,安全性高 |
| 网络通信 | Socket | 支持跨设备 |
| 父子进程通信 | Pipe | 简单高效 |
| 高性能本地通信 | Binder/Socket | 根据需求选择 |
| 需要身份验证 | Binder | 唯一支持 |
七、面试考点
7.1 基础问题
Q1: 什么是 Binder?
参考答案: Binder 是 Android 系统中一种轻量级的进程间通信(IPC)机制,由 Linux 内核驱动实现。它是 Android 系统最核心的通信基础设施,所有系统服务(AMS、PMS、WMS 等)都通过 Binder 进行跨进程通信。Binder 的优势包括:只需一次数据拷贝、支持身份验证和权限检查、基于 Client/Server 模型接口清晰。
Q2: Binder 的架构是怎样的?
参考答案: Binder 架构分为四层:
- 应用层:Java Framework,包含服务的 Java 代理(Stub/Proxy)
- JNI 层:android_util_Binder.cpp,Java 与 Native 的桥梁
- Native 层:libbinder,包含 IBinder、BpBinder、BBinder 等 C++ 类
- Kernel 层:Binder 驱动(/dev/binder),实现内存映射和进程间数据传输
Client/Server/ServiceManager 模型:
- Client:服务调用者(如 App 进程)
- Server:服务提供者(如 AMS、PMS)
- ServiceManager:服务注册中心,管理所有 Binder 服务
Q3: 为什么 Binder 只需要一次数据拷贝?
参考答案: Binder 使用 mmap 实现内存映射:
- 内核分配一块连续的物理内存作为 Binder 缓冲区
- 将这块物理内存同时映射到 Client 和 Server 的用户空间
- Client 写入数据时,从用户空间拷贝到物理内存(1 次拷贝)
- Server 读取数据时,直接访问映射的物理内存(0 次拷贝)
- 总共只需 1 次拷贝,而传统 IPC(Socket/Pipe)需要 2 次
7.2 进阶问题
Q4: Binder 的通信流程是怎样的?
参考答案:
- Server 端通过 ServiceManager.addService() 注册服务
- Client 端通过 ServiceManager.getService() 获取服务 Proxy
- Client 调用 Proxy 方法,打包数据到 Parcel
- 调用 binderProxy.transact(),通过 JNI 进入 Native 层
- BpBinder::transact() → IPCThreadState::transact()
- 通过 ioctl(BINDER_WRITE_READ) 写入 Binder 驱动
- 内核查找目标节点,创建 binder_transaction
- 唤醒 Server 线程,Server 通过 ioctl 读取命令
- Server 调用 onTransact() 处理业务逻辑
- 返回结果给 Client
Q5: ServiceManager 的作用是什么?
参考答案: ServiceManager 是 Binder 架构中的服务注册中心,类似 DNS 服务:
- 服务注册:Server 调用 addService(name, binder) 注册服务
- 服务查询:Client 调用 getService(name) 获取服务 Proxy
- 权限检查:验证调用者是否有权限访问服务
- 服务列表:维护所有已注册服务的映射表
ServiceManager 是一个 Native 进程,PID 为 0 之前的特殊进程,通过 binder_become_context_manager() 成为上下文管理器。
Q6: Binder 的死亡通知机制是怎样的?
参考答案: Binder 死亡通知流程:
- Client 调用 linkToDeath() 注册死亡回调
- 内核在 binder_ref 中记录死亡接收者列表
- Server 进程退出时,内核清理其 binder_node
- 内核向所有注册的 Client 发送 BR_DEAD_BINDER 命令
- Client 的 IPCThreadState 收到命令,触发死亡回调
- Client 可以重连或清理资源
代码示例:
java
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
// Server 死亡,重新获取服务
IBinder newBinder = ServiceManager.getService("activity");
}
}, 0);7.3 深度问题
Q7: Binder 的线程模型是怎样的?
参考答案: Binder 的线程模型包括:
- Client 线程:发起调用的线程,通过 IPCThreadState 发送请求
- Server 线程池:Server 进程启动时创建,默认 15 个线程
- Binder 驱动线程:内核线程,处理跨进程通信
线程池管理:
- ProcessState::startThreadPool() 启动线程池
- PoolThread::threadLoop() 调用 joinThreadPool()
- IPCThreadState::joinThreadPool() 进入循环,等待命令
- 通过 BC_ENTER_LOOPER/BC_REGISTER_LOOPER 注册到驱动
调用链:
Client 线程 → transact() → 内核 → 唤醒 Server 线程 → onTransact() → 返回Q8: Binder 的内存管理是怎样的?
参考答案: Binder 的内存管理包括:
- mmap 区域:每个进程 mmap 一块内核缓冲区(默认 4MB)
- 事务缓冲区:用于存储传输的数据
- 引用计数:通过 strong_ref/weak_ref 管理对象生命周期
- 内存回收:内核在适当时机回收不再使用的内存
内存限制:
- 单个进程 mmap 区域:4MB(可配置)
- 单次事务数据大小:1MB(BINDER_REPLY_LIMIT)
- 总 Binder 内存:系统内存的 1/8
优化建议:
- 避免传输大对象(使用文件描述符)
- 避免频繁的小事务(批量处理)
- 及时释放 Binder 对象(避免内存泄漏)
Q9: Binder 的安全性是如何保证的?
参考答案: Binder 的安全性机制:
- 身份验证:内核自动获取调用者的 UID/PID
- 权限检查:Server 可以检查 Client 的权限
- 服务访问控制:ServiceManager 控制服务访问
- SELinux:额外的强制访问控制
- 签名验证:系统服务需要签名匹配
代码示例:
java
// AMS 检查调用者权限
public int startActivity(...) {
int callingUid = Binder.getCallingUid();
int callingPid = Binder.getCallingPid();
// 检查权限
if (checkPermission(MANAGE_ACTIVITY, callingPid, callingUid)
!= PERMISSION_GRANTED) {
throw new SecurityException("Permission denied");
}
}八、参考资料
本文约 14,000 字,涵盖 Binder 机制的核心知识点。建议结合源码深入理解,并在实际项目中观察 Binder 的行为。