Android多进程这玩意嘛,说真的,平时接触的不多,更别说在正式项目上使用了,也就看书看博客的时候了解了用法,然后面试笔试会问到而已,但为了加深对Android各种机制的理解,今天还是来聊聊多进程之Binder吧。
1、IPC、LPC、RPC
首先我们还是先来搞清这几个概念:
A:IPC(Inter-Process Communication),也就是进程间通信
B:LPC(Local Procedure Call),也就是本地过程调用(单台机器,本地工作)
C:RPC(Remote Procedure Call),也就是远程过程调用(多台机器,网上工作)
D:IPC包含了LPC和RPC两种类型的进程间通信
2、Android开启多进程的方法:
在AndroidManifest.xml中声明组件时,用android:process属性来指定。
适用的元素:Application, Activity, BroadcastReceiver, Service, ContentProvider
如果不值定process属性,则默认运行在主进程中,主进程名字为包名。
android:process = :xxxxx ,将运行在默认包名:xxxxx 进程中,而且是APP的私有进程,不允许其他APP的组件来访问。
android:process = [小写字母开头],表示这个进程为全局进程,可以被多个APP共用。
3、Android开启多进程的好处:
A:增加App可用内存(现在手机内存都较大,若单纯只想增大APP可用内存,可考虑配置largeHeap)
B:独立于主进程(用来确保某些任务的执行和完成)
4、多进程引发的问题:
A:静态成员和单例失效:每个进程保持各自的静态成员和单例,相互独立。
B:线程同步机制失效:每个进程有自己的线程锁。
C:SharedPreferences可靠性下降:不支持并发写,会出现脏数据。
D:Application多次创建:不同进程跑在不同虚拟机,每个虚拟机启动会创建自己的Application,自定义Application时生命周期会混乱。
E:SQLite容易被锁,如果两个进程同时对数据库操作,则会发生SQLiteDatabaseLockedException等异常
5、Linux关于多进程的基础概念——引出Binder
A:Linux的虚拟内存机制导致内存的隔离,进而导致进程隔离
B:进程隔离的出现导致对内存的操作被划分为用户空间和内核空间
C:用户空间需要跨权限去访问内核空间,必须使用系统调用去实现
D:系统调用需要借助内核模块/驱动去完成
E:Binder驱动就是内核模块/驱动中用来实现进程间通讯的
6、为什么要用Binder?
众所周知,Android 系统是基于 Linux 内核的,Linux 已经提供了管道、消息队列、共享内存和 Socket 等 IPC 机制。那为什么 Android 还要提供 Binder 来实现 IPC 呢?主要是基于性能、稳定性和安全性几方面的原因。
如上图(侵删)所示,我们稍微总结一下:
A:Socket 作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信。
B:消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。
C:共享内存虽然无需拷贝,但控制复杂,难以使用。
D:Binder 只需要一次数据拷贝,性能上仅次于共享内存。
最后,我们用以下一张图(侵删)来总结Binder 的优势
7、Binder通信模型
首先在理解模型之前先熟悉这几个概念:
●Client进程:跨进程通讯的客户端(运行在某个进程)
●Server进程:跨进程通讯的服务端(运行在某个进程)
●Binder驱动:跨进程通讯的介质
●ServiceManager:跨进程通讯中提供服务的注册和查询(运行在System进程)
又盗了一张图(侵删),说实话第一眼看到这一张图,我就想起了最近后端开发超火的微服务,这模型简直是一样一样的啊,后来查了一下,阿里的dubbo确实也是基于这样的模型的(RPC嘛)。
我们还是简单描述一下整个过程:
A:Server端通过Binder驱动在ServiceManager中注册
B:Client端通过Binder驱动获取ServiceManager中注册的Server端
C:Client端通过Binder驱动和Server端进行通讯
8、Binder通信原理
又盗一张图(侵删,原作者图画得太赞了),梳理Binder的通讯原理:
A:Service端通过Binder驱动在ServiceManager的查找表中注册Object对象的add方法
B:Client端通过Binder驱动在ServiceManager的查找表中找到Object对象的add方法,并返回proxy对象的add方法,add方法是个空实现,proxy对象也不是真正的Object对象,是通过Binder驱动封装好的代理类的add方法
C:当Client端调用add方法时,Client端会调用proxy对象的add方法,通过Binder驱动去请求ServiceManager来找到Service端真正对象,然后调用Service端的add方法
9、理解Binder对象和Binder驱动
●Binder对象:Binder机制中进行进程间通讯的对象,对于Service端为Binder本地对象,对于Client端为Binder代理对象
●Binder驱动:Binder机制中进行进程间通讯的介质,Binder驱动会对具有跨进程传递能力的对象做特殊处理,自动完成代理对象和本地对象的转换
10、Android系统中Binder的应用
首先,我们来说一下AMS(ActivityManagerService),它可以说是Android应用的最关键最和谐的一个service,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,而我们再来看看AMS中的Binder体系,如下图(侵删):
正是因为AMS中有了Binder机制的支持,我们的四大组件才拥有着跨进程通讯的能力,下面我们逐一进行说明:
A:Activity,通过Action来指定别的进程中的Activity,举个简单的例子,比如打电话
B:ContentProvider,通过Uri.parse("content://authorities")来访问别的APP的共享数据
C:BroadcastReceiver,也是通过Action来指定及过滤的,是一种被动跨进程通讯的方式
D:Service,最典型的例子就是AIDL服务,当然还有Messenger(基于AIDL实现的)
这么说吧,Binder机制在整个Android系统中占着非常重要的地位,举个最简单的例子,APP中的Activity启动startActivity,这一过程都能找到Binder机制的身影,详情请看下图(侵删):
PS:本文只为笔者学习记录,大量参考下面文章:
https://blog.csdn.net/qq_30379689/article/details/79451596
https://www.cnblogs.com/baronzhang/p/8784458.html
https://www.cnblogs.com/cocoabird/p/8392274.html