Android 的进程间通信(IPC)有一套自己的 Binder 机制,而不是像传统 Linux 那样主要依赖 Socket 或共享内存。本文覆盖两块:Binder 的底层组成(Client / Service / ServiceManager / Binder 驱动),以及基于 Binder 封装出来的轻量消息式 IPC——Messenger。多数跨进程场景不需要直接写 AIDL,Messenger 往往够用。


一、Binder 原理:Client / Service / ServiceManager / Binder 驱动

Android 的 Binder 机制由 Client、Service、ServiceManager、Binder 驱动程序四部分组成。Client、Service、ServiceManager 运行在用户空间,Binder 驱动运行在内核空间。Binder 是把这 4 种组件粘合在一起的粘合剂,核心组件是 Binder 驱动,ServiceManager 提供辅助管理,Client 和 Service 在它们提供的基础设施上实现 C/S 通信。

Binder 驱动提供设备文件 /dev/binder 与用户空间交互,Client、Service、ServiceManager 通过 openioctl 与驱动通信。Client 和 Service 的进程间通信经 Binder 驱动间接实现,并非双方直接对接。ServiceManager 是守护进程,管理 Service 并向 Client 提供查询 Service 接口的能力。

三个容易踩的坑

  • Binder 只跑在内核驱动这一层:Client 和 Service 的通信经 Binder 驱动间接完成,别理解成两个进程直接读同一块内存。
  • 跨进程对象不能直塞:能传的只有经 Parcel 序列化的数据,普通 Java 对象过不了 Binder。
  • Service 要先在 ServiceManager 注册:Client 查不到接口,往往是 Service 没起来或没注册,而不是消息发了没收到。

什么时候用:需要高效、带身份校验的跨进程调用(尤其 C/S 架构)时,Binder 是 Android 首选;手写 AIDL 就是在描述这套接口契约。


二、Messenger:基于 Binder 的消息式封装

Messenger 是 Android 基于 Binder 封装的消息式 IPC。服务端在 Handler 里处理 Message,再把 Handler 包成 Messenger 交给客户端。客户端拿到 IBinder 后也能通过 replyTo 发回自己的 Messenger,形成双向通信。队列是串行的:同一时刻只处理一条消息,实现简单,也避免并发改共享状态。比 AIDL 简单,但只适合消息队列语义,不能直接调带返回值的多方法接口。Handler 所在线程决定消息的处理线程。

四个容易踩的坑

  • 只适合消息队列语义:接口少、异步通知用 Messenger;复杂 RPC(多方法、带返回值)用 AIDL。
  • 数据必须能放进 Message / Bundle:注意跨进程 Parcel 大小限制,不要把大 Bitmap 塞进 Message。
  • 死亡通知要监听:服务死亡后监听 DeathRecipient(即 IBinder.linkToDeath),重新 bind,否则发消息会失败。
  • 丢消息先查链路:很多「发了没收到」其实是组件没起来——先确认两个进程是否真的 bind 成功,再看 whatarg 是否对得上;多个客户端共用一个 Messenger 时要自己分发 what

什么时候用:低频、低并发的跨进程通知(比如把状态推给独立进程的服务)用 Messenger;高频或需并发调用时用 AIDL。混淆时要 keep 住 Handler 的 what 常量。


附:Binder 与 Messenger / AIDL 对比

方式 适用场景 不要用它
Binder(AIDL) 复杂 RPC、多方法接口、需并发调用、带身份校验的 C/S 只是发个状态通知的小需求
Messenger 低频、低并发、串行的异步通知 高频并发或需多方法带返回值的 RPC
replyTo 双向 客户端需回传自己的 Messenger 做双向通信 单向就够了却硬上双向链路