参考感谢https://www.jianshu.com/p/4ee3fd07da14
一、什么是 Binder
- 从模型、机制的角度讲:
BIndier 是Android 中跨进程通信的一种方式。 - 从模型的结构、组成来说
BIndier 是一种虚拟的物理设备驱动。连接 server 进程、client 进程、与 ServiceManager 进程。 - 从 Android 的代码角度实现来说
BIndier 是一个 类 继承了 IBinder 接口,是 BIndier 机制模型的 代码实现。
二、Linux 进程模型
1、模型
- 每个进程分为 用户控件与内核空间,二者是隔离的,二者之间数据传递要通过系统的 copy_from_user()与 copy_to_user()拷贝数据。
- 不同进程之间用户控件的数据是不可共享的,而内核空间的数据是所有进程共享的。
- android中为了保证安全性与独立性,一个进程不能操作或访问另一个进程。即进程间是相互独立的、隔离的。
2、 传统的进程间通信
由上信息,可想到传统的进程通信原理:
可通过copy_from_user()与 copy_to_user()以内核空间作为中介 进行数据传递。
但缺点显而易见:
- 数据需要两次拷贝,效率低下
- 接收方进程不知道发来的数据需要多大空间,所以要么开辟尽量大的内存,要么先行传递数据空间大小信息,前者浪费空间,后者浪费时间。
而 通过Binder机制进行 进程间通信,数据只需一次拷贝,同时负责创建接收区缓存空间,与管理接收方缓存的工作。
三、Binder 原理
1、Binder 进程间通信模型
采用 Client — Server 模型。
角色介绍:
1、 Client 进程 ,使用服务的进程。
2、server 进程, 提供服务的进程。
3、 ServerManager, 提供server 进程 Binder 实体的注册,建立该 Binder 的引用,再将字符串形式的 Binder 名字与 Binder 引用维护到一张表中。client 进程则可以通过 所需服务Binder的字符串名字 查询到 Binder 的引用,进而进行进程间通信。
4、 binder 驱动,一种虚拟的物理设备,是 client 、server、与 serviceManager 的桥梁。作用:
- 传递服务进程消息
- 建立内存映射(此处即为 Binder 进行IPC数据只需一次拷贝的秘密)
- 实现线程控制
2、通信的具体步骤
-
server注册服务
- sever 进程想 Binder驱动 发起注册服务请求。
- Bindier 驱动 向 ServiceManager 转发请求。
- ServiceManager 收到请求,注册该服务。
-
client获取服务
- client进程 向 Binder 驱动发起获取服务请求。传递字符串服务名。
- Binder 驱动 转发请求给 ServiceManager
- ServiceManager 查找到对应的服务信息 通过 Binder 驱动将服务信息转发给 client。
至此client 进程与 server 进程已经建立了连接。
-
调用服务
Binder驱动为通信做准备
。创建一块接收缓冲区
。通过 ServiceManager 查到 Server 信息,调用系统的 mmap()函数建立 server进程的
用户空间——内核空间——接收缓冲区 映射关系。client 进程将参赛数据发送到 server 进程
。client 进程通过copy_from_user()函数 像内核空间写入数据,并挂起当前线程。
由于存在映射关系,故相当于数据已经发送到了server 进程的 用户空间。
。Binder 驱动通知 server 进程执行解包server 进程根据 client 的请求 调用目标方法。
。收到 Binder 驱动的通知后 从线程池取出线程,并执行解包、调用目标方法操作
。将执行结果写入自己共享内存中。-
将结果返回给 client
。server 将最终执行结果写入存在映射的用户空间中,由于内存映射关系,想当于 结果传递给了client
。Binder 驱动 通知 client 接收结果,唤醒 client 挂起的线程
。client 通过copy_to_user()将数据拷贝至自己的进程的用户空间。
至此通信结束
优点:
每次单向通信只需一次内存拷贝,传输效率高。
为接收进程分配了不确定大小的接受缓冲区
三、一些疑问点
1、为什么 Client 进程、Server 进程、ServiceManager 进程之间的交互都必须通过 Binder 驱动?
参照上文中 Linux 进程模型
- Client进程、Server进程 & Service Manager进程属于进程空间的用户空间,不可进行进程间交互。
- Binder驱动 属于 进程空间的 内核空间,可进行进程间 & 进程内交互。
2、ServiceManager是参与 BInder 机制的,但是为什么与ServiceManager 进程通信也是用的 Binder 机制?
Binder驱动 & Service Manager进程 属于 Android基础架构(即系统已经实现好了);而Client 进程 和 Server 进程 属于Android应用层(需要开发者自己实现)