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 系统开发的必经之路。

相关推荐
私人珍藏库17 小时前
【Android】图片工具箱-免费开源图片处理软件
android·人工智能·app·工具·软件·多功能
武当王丶也17 小时前
React Native Turbo Module 实战:从 0 封装一个 PDA 扫码模块
android·前端·react native
2501_9159184117 小时前
Linux 上生成 AppStoreInfo.plist,App Store 上架 iOS
android·ios·小程序·https·uni-app·iphone·webview
黄林晴17 小时前
Kotlin 官方发布kotlin-agent-skills,迁移/转换一键规范
android·kotlin
私人珍藏库17 小时前
【Android】ActionDot悬浮触控(高级版)一个悬浮球包含一切
android·人工智能·app·工具·软件·多功能
私人珍藏库17 小时前
【Android】小思AI2.1学习工具-内置海量学习游戏-帮助学 -最强一对一辅导补习
android·学习·游戏·app·工具·软件·多功能
我命由我1234518 小时前
Dart - 数字类型、布尔类型、列表类型
android·开发语言·flutter·ios·uni-app·android jetpack·移动端
Kapaseker18 小时前
Kotlin 准备引入 [1,2,3] 创建集合
android·kotlin
码上有光18 小时前
MySQL——复合查询
android·数据库·mysql·期末快速复习