Skip to content

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

特性BinderSocketPipeMessageQueue
性能⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
安全性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
易用性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
跨进程
跨设备
身份验证
数据拷贝次数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)                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

核心类说明

作用位置
IBinderBinder 接口基类Native
BpBinderBinder Proxy(客户端代理)Native
BBinderBinder 实体(服务端)Native
BnInterfaceStub 基类模板Native
BpInterfaceProxy 基类模板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 的核心实现。

核心功能

  1. 进程间数据传输:通过内存映射实现高效数据传输
  2. 线程管理:管理 Binder 线程池
  3. 引用计数:管理 Binder 对象的生命周期
  4. 权限检查:验证调用者 UID/PID
  5. 死亡通知:通知 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 性能对比

指标BinderSocketPipe
数据拷贝1 次2 次2 次
延迟
吞吐量
连接建立

6.2 功能对比

功能BinderSocketPipe
跨进程
跨设备
身份验证
权限检查
死亡通知
一对一
一对多
同步调用
异步调用

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 架构分为四层:

  1. 应用层:Java Framework,包含服务的 Java 代理(Stub/Proxy)
  2. JNI 层:android_util_Binder.cpp,Java 与 Native 的桥梁
  3. Native 层:libbinder,包含 IBinder、BpBinder、BBinder 等 C++ 类
  4. Kernel 层:Binder 驱动(/dev/binder),实现内存映射和进程间数据传输

Client/Server/ServiceManager 模型:

  • Client:服务调用者(如 App 进程)
  • Server:服务提供者(如 AMS、PMS)
  • ServiceManager:服务注册中心,管理所有 Binder 服务

Q3: 为什么 Binder 只需要一次数据拷贝?

参考答案: Binder 使用 mmap 实现内存映射:

  1. 内核分配一块连续的物理内存作为 Binder 缓冲区
  2. 将这块物理内存同时映射到 Client 和 Server 的用户空间
  3. Client 写入数据时,从用户空间拷贝到物理内存(1 次拷贝)
  4. Server 读取数据时,直接访问映射的物理内存(0 次拷贝)
  5. 总共只需 1 次拷贝,而传统 IPC(Socket/Pipe)需要 2 次

7.2 进阶问题

Q4: Binder 的通信流程是怎样的?

参考答案

  1. Server 端通过 ServiceManager.addService() 注册服务
  2. Client 端通过 ServiceManager.getService() 获取服务 Proxy
  3. Client 调用 Proxy 方法,打包数据到 Parcel
  4. 调用 binderProxy.transact(),通过 JNI 进入 Native 层
  5. BpBinder::transact() → IPCThreadState::transact()
  6. 通过 ioctl(BINDER_WRITE_READ) 写入 Binder 驱动
  7. 内核查找目标节点,创建 binder_transaction
  8. 唤醒 Server 线程,Server 通过 ioctl 读取命令
  9. Server 调用 onTransact() 处理业务逻辑
  10. 返回结果给 Client

Q5: ServiceManager 的作用是什么?

参考答案: ServiceManager 是 Binder 架构中的服务注册中心,类似 DNS 服务:

  1. 服务注册:Server 调用 addService(name, binder) 注册服务
  2. 服务查询:Client 调用 getService(name) 获取服务 Proxy
  3. 权限检查:验证调用者是否有权限访问服务
  4. 服务列表:维护所有已注册服务的映射表

ServiceManager 是一个 Native 进程,PID 为 0 之前的特殊进程,通过 binder_become_context_manager() 成为上下文管理器。

Q6: Binder 的死亡通知机制是怎样的?

参考答案: Binder 死亡通知流程:

  1. Client 调用 linkToDeath() 注册死亡回调
  2. 内核在 binder_ref 中记录死亡接收者列表
  3. Server 进程退出时,内核清理其 binder_node
  4. 内核向所有注册的 Client 发送 BR_DEAD_BINDER 命令
  5. Client 的 IPCThreadState 收到命令,触发死亡回调
  6. Client 可以重连或清理资源

代码示例

java
binder.linkToDeath(new DeathRecipient() {
    @Override
    public void binderDied() {
        // Server 死亡,重新获取服务
        IBinder newBinder = ServiceManager.getService("activity");
    }
}, 0);

7.3 深度问题

Q7: Binder 的线程模型是怎样的?

参考答案: Binder 的线程模型包括:

  1. Client 线程:发起调用的线程,通过 IPCThreadState 发送请求
  2. Server 线程池:Server 进程启动时创建,默认 15 个线程
  3. Binder 驱动线程:内核线程,处理跨进程通信

线程池管理

  • ProcessState::startThreadPool() 启动线程池
  • PoolThread::threadLoop() 调用 joinThreadPool()
  • IPCThreadState::joinThreadPool() 进入循环,等待命令
  • 通过 BC_ENTER_LOOPER/BC_REGISTER_LOOPER 注册到驱动

调用链

Client 线程 → transact() → 内核 → 唤醒 Server 线程 → onTransact() → 返回

Q8: Binder 的内存管理是怎样的?

参考答案: Binder 的内存管理包括:

  1. mmap 区域:每个进程 mmap 一块内核缓冲区(默认 4MB)
  2. 事务缓冲区:用于存储传输的数据
  3. 引用计数:通过 strong_ref/weak_ref 管理对象生命周期
  4. 内存回收:内核在适当时机回收不再使用的内存

内存限制

  • 单个进程 mmap 区域:4MB(可配置)
  • 单次事务数据大小:1MB(BINDER_REPLY_LIMIT)
  • 总 Binder 内存:系统内存的 1/8

优化建议

  • 避免传输大对象(使用文件描述符)
  • 避免频繁的小事务(批量处理)
  • 及时释放 Binder 对象(避免内存泄漏)

Q9: Binder 的安全性是如何保证的?

参考答案: Binder 的安全性机制:

  1. 身份验证:内核自动获取调用者的 UID/PID
  2. 权限检查:Server 可以检查 Client 的权限
  3. 服务访问控制:ServiceManager 控制服务访问
  4. SELinux:额外的强制访问控制
  5. 签名验证:系统服务需要签名匹配

代码示例

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");
    }
}

八、参考资料

  1. Android 源码 - Binder 驱动
  2. Android 源码 - libbinder
  3. Android 源码 - Binder.java
  4. Binder 设计与实现
  5. Android IPC 机制详解

本文约 14,000 字,涵盖 Binder 机制的核心知识点。建议结合源码深入理解,并在实际项目中观察 Binder 的行为