android Binder 讲解

Android Binder 详解

1. 什么是 Binder?

Binder 是 Android 系统中最核心的跨进程通信(IPC)机制 ,负责几乎所有系统服务(如 ActivityManager、WindowManager)与应用程序之间的通信。它基于客户端-服务器模式,具有高性能、安全性高的特点。

2. 为什么需要 Binder?

Android 基于 Linux 内核,Linux 已有多种 IPC 方式(管道、Socket、共享内存等),但 Google 选择开发 Binder,原因如下:

特性 Binder 传统 IPC(如 Socket)
性能 高(仅一次内存拷贝) 较低(两次拷贝)
安全性 支持 UID/PID 验证 需手动管理
同步模型 同步调用,类似函数调用 异步或需额外封装
实现复杂度 较高 较低

核心优势 :Binder 在传输数据时,只拷贝一次(从发送方用户空间到内核空间,接收方映射同一块内存),而传统方式通常需要两次拷贝。

3. Binder 通信模型

采用经典的 C/S(客户端-服务器)架构,包含四个角色:

css 复制代码
[Client]  <--->  [Binder Driver (内核)]  <--->  [Server]
                     ↑
                     |
                 [Service Manager]
  • Client:服务的使用者(如 App 请求 AMS)
  • Server:服务的提供者(如 AMS、WMS)
  • Binder Driver:内核驱动(/dev/binder),负责数据中转、线程管理
  • Service Manager:服务注册与查询的"电话总机"

4. 工作流程

步骤拆解:

  1. Server 注册

    Server 向 Service Manager 注册服务,告诉 SM:"我提供了 XX 服务,这是我的 Binder 引用"。

  2. Client 获取代理

    Client 向 SM 查询服务,SM 返回一个 Binder 代理对象(实际上是句柄)。

  3. Client 调用方法

    Client 调用代理对象的接口方法(如 activityManager.startActivity())。

  4. 数据打包与发送

    Binder 驱动将参数序列化(Parcel),从 Client 进程拷贝数据到内核空间,并找到目标 Server 进程。

  5. Server 执行

    内核唤醒 Server 进程的 Binder 线程池,将数据解包并调用实际实现。

  6. 返回结果

    Server 执行完成后,结果沿原路返回给 Client。

关键点 :对于 Client 来说,调用远程服务方法就像调用本地函数一样(透明性),但实际上线程会阻塞等待返回。

5. 一次数据拷贝原理

Binder 性能高的核心在于内存映射(mmap)

  • 内核为每个 Server 进程预先映射一块内存(Binder 驱动管理的缓冲区)
  • 当 Client 发送数据时,数据直接从 Client 用户空间 → 内核空间(第一次拷贝)
  • 由于 Server 的 mmap 将同一块内核内存映射到自己的用户空间,无需再次拷贝数据
  • Server 直接读取自己的用户空间地址即可获得数据
arduino 复制代码
传统 IPC:Client 用户空间 -> 内核空间 -> Server 用户空间 (2次)
Binder:   Client 用户空间 -> 内核空间 (Server 通过 mmap 直接可见) (1次)

6. Binder 通信协议

6.1 数据包格式(Binder 协议)

Binder 驱动识别的协议分为:

  • BC 协议(Binder Command):Client/Server → Driver 的命令
  • BR 协议(Binder Return):Driver → Client/Server 的返回

常用命令:

  • BC_TRANSACTION:发送请求数据
  • BR_TRANSACTION:接收请求数据
  • BC_REPLY:发送响应数据
  • BR_REPLY:接收响应数据

6.2 Parcel(数据序列化)

Binder 使用 Parcel 类完成数据的打包与解包,支持基本类型、Binder 对象、文件描述符等。

cpp 复制代码
// C++ 示例
Parcel data, reply;
data.writeInt32(0);
data.writeString16("com.example.MyService");
remote->transact(CODE_START, data, &reply);

7. Binder 架构层次

从底层到上层:

层次 组件 语言 作用
内核层 Binder Driver C 驱动,处理通信核心
Native 层 libbinder(BBinder/BpBinder) C++ 提供 Binder 框架基础类
Native 层 ServiceManager C++ 服务注册与查找
Framework 层 Binder.java / IBinder Java JNI 调用 Native 接口
Framework 层 AIDL Java 自动生成跨进程通信接口代码

核心类对应关系:

  • IBinder:Binder 对象的基础接口
  • BpBinder(Proxy):客户端代理
  • BBinder(Native):服务端真实对象
  • Binder(Java):BBinder 的 Java 封装

8. 代码示例

AIDL 定义(IHello.aidl):

java 复制代码
interface IHello {
    String sayHello(String name);
}

生成的 Stub 类结构:

scss 复制代码
IHello.Stub (服务端)
    ├── onTransact() // 接收客户端请求
    └── asInterface() // 返回服务端或代理

IHello.Stub.Proxy (客户端自动生成的代理)
    └── sayHello() // 内部调用 transact()

服务端实现:

java 复制代码
private final IHello.Stub mBinder = new IHello.Stub() {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }
};

客户端调用:

java 复制代码
IHello service = IHello.Stub.asInterface(binderProxy);
String result = service.sayHello("Android"); // 跨进程调用

9. 线程模型

  • 每个 Server 进程在初始化时会启动 Binder 线程池(默认 16 个线程)
  • 当 Client 请求到来时,Binder 驱动会从线程池中分配一个线程执行请求
  • 如果线程池耗尽,请求会被挂起等待

注意事项

服务端实现不能做耗时操作,否则会占用 Binder 线程,导致其他客户端阻塞。耗时任务应另起线程处理。

10. 安全机制

  • UID/PID 验证:Binder 驱动会自动记录调用者的进程 ID 和用户 ID
  • 权限检查 :服务端可调用 Binder.getCallingUid() 获取调用者身份,判断是否有权限
  • 不可伪造:调用方的 UID/PID 由内核提供,无法在用户态伪造

11. 常见问题

Q1:Binder 传输数据大小有限制吗?

,默认最大为 1MBBINDER_VM_SIZE)。传输大数据(如图片)应使用共享内存(MemoryFile)或文件(ContentProvider)。

Q2:为什么 Android 用 Binder 而不是 D-Bus?

  • D-Bus 基于 Socket,性能较低
  • D-Bus 设计用于桌面环境,没有 UID/PID 传递
  • Binder 更轻量,适合移动设备资源受限的场景

Q3:ServiceManager 的句柄为什么总是 0?

Service Manager 本身的 Binder 句柄固定为 0,任何进程都可以通过 Binder.getService("manager") 获取它。

12. 总结

方面 总结
定义 Android 的核心跨进程通信(IPC)机制
模型 客户端-服务器模型,含 Binder 驱动和 Service Manager
性能 一次内存拷贝,传输效率高
安全性 内核级 UID/PID 校验,天然支持权限控制
使用方式 通过 AIDL 自动生成代码,开发简单

Binder 不仅仅是 IPC 工具,更是整个 Android 系统服务的 "血管",理解它是深入 Android 系统开发的必经之路。

相关推荐
ltlovezh11 小时前
ROI 编码学习指南:Android 与 FFmpeg 的真实实现边界
android·ffmpeg·音视频开发
心前阳光12 小时前
Unity之2021.3.45f2c1发布安卓程序遇到的问题
android·unity·游戏引擎
utf8mb4安全女神13 小时前
MySQL5.7升级到MySQL8.0并进行数据迁移
android
黄林晴13 小时前
Android XR DP4 重磅发布:手机 App 直投眼镜,Compose 原生玩转 3D 内容
android·google io
炼川淬海DB15 小时前
数据库开发规范
android·adb·数据库开发
2501_9159184115 小时前
iOS App性能测试工具的实现方法与优化循环指南
android·ios·小程序·https·uni-app·iphone·webview
天天爱吃肉821815 小时前
豆包 vs DeepSeek API 对比分析报告
android·java·大数据·开发语言·功能测试·嵌入式硬件·汽车
问心无愧051316 小时前
ctf show web入门123
android·前端·笔记
想你依然心痛17 小时前
手机远程控制电脑教程:安卓iOS远程桌面推荐、免费工具配置与远程办公技巧
android·智能手机·电脑