前言
在 Android 开发过程中常常会涉及到 Binder 的应用,特别是在 Framework 层的开发过程,因此了解 Binder 的运行机制是至关重要的。本系列致力于用通俗易懂的方式来梳理从上层应用到底层驱动的整个过程。在此之前我们先对涉及到的内容做一些了解,本系列文章均基于Android 8
一、IPC 原理
IPC (InterProcess Communication) 进程间通信,是指在不同进程之间传播或者交换信息。在 Linux 中,每个进程都有自己的 虚拟内存地址空间。同时虚拟内存地址空间又划分为 用户地址空间 和 内核地址空间,如下图所示:

不同进程之间的用户地址空间映射到不同的物理地址,所以不同进程之间用户地址空间的变量和函数是不能相互访问的。但不同的内核地址空间是映射到相同的物理地址的,它们是相同和共享的,因此可以借助内核地址空间作为中转站来时吸纳进程间数据的传输。这样当我们在 进程B 中使用 copy_from_user 内核函数将用户态数据 int a 拷贝到内核态,这样就可以在 进程A 的内核态中访问到 int a

当 进程A 中使用 copy_to_user 函数就可以将内核地址空间的 int a 拷贝到用户地址空间,这样就顺利的实现跨进程的数据访问了。

但这个过程中存在一个问题:为了访问 int a , 需要拷贝两次,这势必会影响到效率,因此我们可以通过 mmap 将进程 A 的用户地址空间与内核地址空间进行映射,让他们指向相同的物理地址空间,同时 B 进程对应的内核地址空间同样指向这块物理内存:

二、RPC 原理
RPC (Remote Procedure Call) 翻译为 远程过程调用,通常是 CS 架构的方式,即在 Client 进程中可以访问 Server 进程中的函数。Binder 就是一个 RPC 架构,RPC 是在 IPC 基础上进行的封装, IPC 负责数据的跨进程传输, 其应用层框架如下所示:

这样:
- Server 进程中那些等待被远程调用的函数集合,我们称其为 Binder 服务 (Binder Service)
- 服务 (Service) 需要先注册到 服务管家(ServiceManager)
- 服务管家(ServiceManager) 是在 Android 系统启动时,启动的一个用于管理 Binder 服务 (Binder Service) 的进程,其内部通过一个链表服务的相关信息
- 服务(Service) 注册到 服务管家(ServiceManager)后,Client 才能从 服务管家(ServiceManager)获取到服务的必要信息
- Binder 的跨进程数据传输能力是通过 Binder 驱动实现的
那么我们需要知道的是 Binder 的 RPC 是如何实现的?一般来说是遵循如下规则:
- 在 Client 进程中按照固定的规则打包数据
- Client 进程通过 IPC 机制 将数据传输给 Server 进程
- Server 进程收到数据,按照固定的格式解析出数据,调用函数,并使用相同的格式将函数的返回值传递给 Client 进程
