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

相关推荐
奈斯先生Vector6 小时前
当模型版本不断变化,RelayRouter 能否帮助 AI 应用摆脱深度绑定
android·java·人工智能·开源·aigc
TimeFine6 小时前
让强模型做“总工”,让高性价比模型写代码
android
又见情义8 小时前
RK3568 Android 13 屏蔽 healthd 电池日志经验分享
android
古法安卓11 小时前
Android-Fork 机制详解
android·java·android studio
Android打工仔11 小时前
不要在 Data 层随意把 Cold Flow 转换成 Hot Flow
android·架构·kotlin
峥嵘life12 小时前
2026免费的 opencode 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言
杉氧12 小时前
拒绝重复造轮子:我写了一个生产级的 Kotlin 协程与 Flow 工具库(CoroutineKit)
android·kotlin·workflow
恋猫de小郭13 小时前
Flutter GSoC 2026 提案进度解读,补上 DevTools、FFI 和原生平台的关键缺口
android·前端·flutter
2501_9159090613 小时前
怎么用 FlutterFlow 把应用发布到 App Store?
android·ios·小程序·https·uni-app·iphone·webview
峥嵘life13 小时前
2026华为AI码道 CodeArts 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言·python