跳到主要内容

Binder 机制

问题

Android Binder 机制的原理是什么?为什么选择 Binder 而不是传统 Linux IPC?

答案

为什么选择 Binder

特性共享内存Socket管道Binder
拷贝次数0 次2 次2 次1 次
安全性低(无身份验证)高(UID/PID)
C/S 架构
易用性复杂(同步控制)中等简单好(AIDL 自动生成)

Binder 在性能(一次拷贝)和安全性(内核验证调用方身份)之间取得了最佳平衡。

Binder 通信原理

一次拷贝的关键:mmap

传统 IPC(如 Socket)需要两次拷贝:

  1. 发送方用户空间 → 内核空间
  2. 内核空间 → 接收方用户空间

Binder 通过 mmap(内存映射)将接收方的用户空间内核缓冲区映射到同一块物理内存。因此只需一次拷贝(从发送方到内核缓冲区),接收方直接读取映射的内存即可。

Binder 架构

  • ServiceManager:Binder 的"DNS",管理所有注册的服务
  • Proxy(客户端代理):将调用参数打包为 Parcel,通过 Binder 驱动发送
  • Stub(服务端存根):从 Parcel 解包参数,调用真正的业务方法

Android 中的 Binder 应用

  • startActivity() → AMS(ActivityManagerService)通过 Binder
  • getSystemService() → 各种系统服务通过 Binder
  • ContentProvider 底层通过 Binder 跨进程传输数据
  • AIDL 是 Binder 的上层封装

常见面试问题

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

答案

有。Binder 事务缓冲区默认大小为 1MB(所有正在进行的事务共享,非单个事务独占)。传输大数据时会抛出 TransactionTooLargeException。大数据应通过文件、ContentProvider 或 共享内存(MemoryFile / SharedMemory)传输。

Q2: Binder 如何保证安全性?

答案

Binder 驱动在内核中为每次通信附加调用方的 UID 和 PID,这些信息由内核填充,调用方无法伪造。服务端通过 Binder.getCallingUid()Binder.getCallingPid() 获取调用方身份,进行权限验证。这比 Socket 等需要应用层自行验证身份的方式安全得多。

Q3: Binder 调用是同步还是异步?

答案

默认是同步的——Client 调用后会阻塞等待 Server 返回。可以通过 AIDL 中声明 oneway 关键字使调用变为异步(Client 发送后立即返回,不等待 Server 处理完成)。

相关链接