(本文建议学习时长:>3天)
相关文章推荐:
前言
我们知道,Android的底层是使用Linux内核运行的,而Linux为了保证系统的稳定性,使用的是进程隔离的机制,也就是让不同的进程运行在不同的虚拟空间,使得不同进程之间无法共享数据,防止数据的篡改。关于多进程的基础使用及优缺点的介绍链接中已经讲的很清楚了。但是,有时候我们也会遇到不同进程间需要通信的情况,那么,这时候就需要使用Android系统进程间通信IPC(Inter-Process Communication)。
IPC进程间通信方式
名词 | 适用场景 | 缺点 | 优点 |
---|---|---|---|
Bundle | 三大组件(activity、service、receiver)都支持Intent中传递Bundle数据的 | 只能支持基本类型和对象或对象数组且实现Serializable或Parcelable接口 |
简单易用 |
文件共享 | 两个进程间通过读/写同一个文件来交换数据。(传统进程通信) |
不适合高并发场景,无法做到进程间即时通讯 | 简单易用 |
AIDL | 底层通过Binder实现,适合远程服务跨进程一对多即时通信的场景 | 使用复杂,需要做线程同步 | 高并发、实时通讯、且有RPC需求 |
Messenger | 底层由AIDL实现。适合低并发的一对多即时通讯,且无RPC需求 | 不适合高并发情形,不支持RPC,只能传输Bundle支持的类型 | 支持一对多串行即时通信 |
ContentProvider | Android专门用于进程间一对多数据共享的方式,底层实现是Binder | 可以理解为受约束的AIDL,只能提供数据源CRUD(增删改查)操作 | 访问数据源支持一对多并发数据共享,可通过call方法扩展其他操作 |
Socket | 称为“套接字”,用于网络通信中。它分为流式套接字和用户数据套接字,分别应于网络的传输控制层中的TCP和UDP协议 |
实现细节繁琐,不支持直接的RPC | 通过网络传输字节流,支持一对多高并发即时通信 |
*RPC(Remote Procedure Call的缩写) 是远程进程调用的意思。
*Binder线程池最大数为16,超过的请求会被阻塞。在进程间通信时处理并发时,如ContentProvider
的CRUD(增删改查)操作方法最多有16个线程同时工作。
一、Binder的产生
在Linux中规定一个进程分为用户空间和内核空间。区别是,用户空间的数据不可在进程间共享,为了保证数据安全性 、独立性,即进程隔离。而内核空间可以被共享且所有用户空间共享一个内核空间。用户空间与内核空间的通信是使用系统调用:
copy_from_user();//将用户空间的数据拷贝到内核空间
copy_to_user();//将内核空间的数据拷贝到用户空间
传统跨进程通信的基本原理:
- “进程1”通过系统调用copy_form_user() 将需要发送的数据拷贝到Linux进程的内核空间中的缓冲区。(拷贝第一次)
- 内核服务程序唤醒“进程2”的接收线程,通过系统调用copy_to_user() 将数据发送到用户空间。(拷贝第二次)
由于传统的跨进程通信需拷贝数据2次,且接收方事先并不知道需要创建多大的缓存空间用来接收数据,造成了资源浪费。而采用Binder机制实现通信的时候,通过内存映射调用Linux下的系统调用方法mmap(),只需系统调用copy_from_user()拷贝1次数据就可以实现进程间传递数据,节省了内存,提高了效率。
1、内存映射
通过关联一个进程中的一个虚拟内存区域和一个磁盘上的对象,使得二者存在映射关系。被映射的对象称为共享对象。当多个进程的虚拟内存区域和同一个共享对象建立映射关系时,对进程1的虚拟内存区域进行写操作时,也会映射到进程2中的虚拟内存区域。
2、 系统调用mmap()
该函数主要是创建虚拟内存区域 与 共享对象建立映射关系。用内存读写代替 I/O读写。
/**
* 函数原型
*/
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
内部原理:
- 步骤1:创建虚拟内存区域
- 步骤2:实现地址映射关系(进程的虚拟地址空间关联到共享对象)
使用时:
用户进程直接调用mmap()建立映射。
/**
* MAP_SIZE的接收缓存区大小 , 关联到共享对象中,即建立映射
*/
mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
二、Binder机制
1. 定义
Binder是Android中的一个类,它实现了IBinder接口。
从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在Linux中没有。
从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager等等)和相应ManagerService的桥梁。
从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过Binder对象,客户端就可以获取服务端提供的服务或者数据。这里的服务包括普通服务和基于AIDL的服务。
2. 模型
从字面上理解binder是"粘结剂"的意思,那么google的工程师为什会以"粘结剂"来命名binder呢?这是因为binder是基于C-S架构,而在这个模型中存在着四个角色,如下:
角色 | 作用 |
---|---|
Client 客户端进程 | 使用服务的进程 |
Server 服务端进程 | 提供服务的进程 |
ServiceManager 进程 | 管理Service 的注册于查询,类似于路由器 |
Binder驱动 |
|