Binder 通信基础概念

Binder 是 Android 系统最核心的跨进程通信(IPC,Inter-Process Communication)机制,其设计与实现深度依赖操作系统底层的进程隔离、内核态/用户态划分、内存映射(mmap)以及一个专用的内核驱动。理解这四个支柱,是掌握 Binder 原理与开发的起点。本章从底层硬件逐步向上拆解,为后续章节 ServiceManager、AIDL、IPC 线程池、Buffer 管理等实现做铺垫。

1. 进程隔离与虚拟地址空间

在 32 位 ARM Linux 上,每个进程拥有独立的 4GB 虚拟地址空间:

  • 进程隔离:进程 A 无法直接访问进程 B 的虚拟地址,硬件的 MMU(内存管理单元)阻止跨进程物理地址转换。
  • 必要性:防止恶意应用窃取支付密码或篡改系统服务数据;即使单个进程崩溃,也不会直接拖垮整个系统。
  • IPC 挑战:隔离的地址空间迫使跨进程通信必须通过内核中转,Binder 正是为了高效解决这一中转而设计。

2. 用户空间与内核空间

ARMv7/ARMv8 架构通过异常级别(Exception Levels)划分特权域:

空间特权级别地址范围(典型 32 位)直接访问硬件
用户空间EL0(无特权)0x00000000 – 0xBFFFFFFF (3G)否
内核空间EL1(特权)0xC0000000 – 0xFFFFFFFF (1G)是

用户进程必须通过系统调用(syscall)陷入内核才能操作设备、分配共享内存或唤醒其他进程。Binder 驱动面对的 /dev/binder 设备文件正是这个陷入点的入口。

3. mmap 原理与单次拷贝

mmap(内存映射)将内核缓冲区直接映射到用户进程的虚拟地址空间。Binder 利用这一特性实现了“单次拷贝”传输:

  1. 服务端进程在初始化时通过 mmap 向 Binder 驱动申请一块内核物理内存,并映射到自身用户空间。
  2. 客户端发送数据时,驱动在内核中将数据 直接拷贝 到服务端已映射的内核缓冲区。
  3. 服务端无需再通过 read/write 将数据从内核搬运到用户态,因为该缓冲区已经在它的用户地址空间中可见。
对比传统 IPC(如 Socket 或 Pipe)
传统方式:客户端(用户)→ 内核 → 服务端(用户)需要两次拷贝(用户→内核,内核→用户)。
Binder 方式:客户端(用户)→ 内核(mmap 区)→ 服务端(用户)只需一次拷贝(用户→内核),服务端直接访问共享映射区。

4. Binder 驱动的核心角色

Binder 驱动(/dev/binder)在 Linux 内核中承担 IPC 中枢的职责:

  • 设备节点管理:注册 misc 设备,提供 open、mmap、ioctl 接口。
  • 事务路由:根据 handle/ptr 将客户端请求转发到目标服务端线程。
  • Buffer 管理:通过内核 slab 分配器管理 mmap 共享缓冲区,实现零拷贝接收。
  • 引用计数:维护 Binder 实体(local 对象)和 Binder 代理(remote 对象)的强弱引用,防止内存泄漏。

在 Android 设备上可以通过以下命令确认 Binder 驱动是否正常加载:

adb shell ls -l /dev/binder
crw-rw-rw- 1 root root 10, 54 2024-01-01 00:00 /dev/binder

adb shell cat /proc/binder/proc | head -n 10  # 查看当前进程的 Binder 状态
Binder 跨进程通信基础架构 Binder 跨进程通信基础架构 用户空间(User Space) 内核空间(Kernel Space) 进程 A(客户端) Binder Proxy / 代理 进程 B(服务端) Binder Stub / 存根 Binder 驱动 /dev/binder / ioctl mmap 共享缓冲区 单次拷贝承载区 物理内存(RAM) 系统调用 (ioctl) 唤醒 / 回调 拷贝数据 mmap 映射(零拷贝) 关键设计 驱动在内核拷贝数据到 mmap 区后, 服务端通过已建立的映射直接读取。
实现提示(mmap 大小控制)
在 Android 原生代码中,服务端通过 BINDER_VM_SIZE(默认 4 个物理页,共 16KB)控制每个连接能映射的缓冲区上限。如果传输的数据量超过此值,驱动会降级为“两次拷贝”的备用路径,性能会明显下降。部署高吞吐服务(如视频帧传输)时,务必根据实际负载调大 mmap 映射空间。
常见误区
初学者常认为 Binder 的“单次拷贝”意味着完全不涉及 CPU 拷贝。实际上内核驱动必须将用户空间数据拷贝到内核 mmap 缓冲区,这 1 次拷贝是不可避免的。真正的优势在于接收方不需要第 2 次拷贝,而是直接读取映射区域。对比传统 socket 的两次拷贝,Binder 在跨进程大数据传输场景下能降低约 50% 的 CPU 开销。