1.Android开启多进程的方式
在AndroidManifest中给四大组件指定android:process=""属性
2.Android多进程通信的方式
1.四大组件中的BroadcastReceiver ,ContentProvider
2.AIDL
3.Messenger
4.Binder
2.使用多进程会造成什么问题
Android为每个进程分配一个单独的虚拟机,每个虚拟机在内存上有不同的地址空间,导致不同虚拟机中访问同一个类的对象会产生多份副本,在一个进程中修改的只是本进程的副本,不会影响其他虚拟机中的对象
a.静态成员和单例模式完全失效
b.线程同步机制完全失效
锁失效,因为不同进程的锁对象不是同一个
c.SharePreference的可靠性下降
两个进程同时写,会导致数据一定几率的丢失
d.Application会多次创建
当一个组件运行在一个新的进程中,系统要创建新的进程同时分配独立的虚拟机,所以这个过程就是一个启动应用的过程,会导致Application重新创建
IPC基础概念
Serializable Parcelable
区别
1.Serializable是Java中的序列化接口,使用简单但是开销很大,序列化和反序列化过程会设计大量IO操作
2.Parcelable是Android中的序列化方式,更适合在Android平台使用,缺点是使用麻烦但是效率很高,
3.Parcelable主要用在内存序列化上,通过它将对象序列化到存储设备中或者将对象序列化后通过网络传输也是可以的,(marshall: Parcel 将自身所保存的所有数据以 byte 数组的形式返回,然后转为字符串存储,unmarshall: 从 byte 数组里获取数据,存入自身 Parcel,然后调用对应类中CREATOR.createFromParcel转化得到对象),但是这个过程会比较复杂,所以这两种情况推荐使用Serializable,
Binder
Binder涉及到的类
截屏2021-07-15 上午7.42.05.pngBinder驱动
截屏2021-07-15 上午7.42.22.pngBinder框架
截屏2021-07-14 上午8.01.55.png什么是binder
binder有什么优势(字节跳动)
截屏2021-07-14 上午8.03.41.png1.性能。Binder只需要一次数据拷贝,传统IPC方式管道,消息队列,Socket都要两次,共享内存方式只需要一词,但实现复杂,不适合移动设备,binder通过驱动在内核空间拷贝数据,不需要额外的同步处理
2.安全。binder机制协议支持对通信双方身份做校验,Binder 机制为每个进程分配了 UID/PID 来作为鉴别身份的标示,并且在 Binder 通信时会根据 UID/PID 进行有效性检测
3.调用简单。基于C/S架构,面向对象的调用方式,使用binder就像调用一个本地实例
binder如何做到一次内存拷贝(腾讯)
内存被操作系统划分成两块:用户空间和内核空间,用户空间是用户程序代码运行的地方,内核空间是内核代码运行的地方。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。
传统IPC通信的方式需要经过两次拷贝,首先数据从发送方发出,通过copy_from_user()将数据从用户空间拷贝到内核缓存区,然后通过copy_to_user()将数据从内核缓存区拷贝到用户空间,接收方接收到数据,完成一次进程通信。
截屏2021-07-14 上午8.25.31.png
Binder通信的方式只需要一次拷贝,同样首先通过copy_from_user()将数据从用户空间拷贝到内核缓存区,此时数据不需要再从内核空间拷贝到用户空间,因为数据接收方在打开binder设备时,已经对内核空间形成了映射(mmap() memroy map 内存映射
),所以数据对它时可见的
mmap的原理讲解(腾讯)
Linux通过将一个虚拟内存区域与一个磁盘上的对象关联起来,以初始化这个虚拟内存区域的内容,这个过程称为内存映射(memory mapping)。对文件进行mmap,会在进程的虚拟内存分配地址空间,创建映射关系。实现这样的映射关系后,就可以采用指针的方式读写操作这一段内存,而系统会自动回写到对应的文件磁盘上
binder的线程管理
每个binder的server进程会创建很多线程来处理binder请求,可以理解为线程池,这些线程由binder驱动进行管理,一个进程的binder线程数默认最大16,所以同时只能有16个线程在跑
binder的运行机制
基于C/S通信模式,包含四个通信角色:Client进程,Server进程,ServiceManager进程,Binder驱动
ServiceManager进程的作用是将字符形式的binder名转化为client中对该binder的引用,使得client能够通过binder名字获得对server中binder实体的引用
binder驱动的作用是负责建立进程间binder通信,binder在进程间的传递,binder引用计数管理,数据包在进程之间的传递和交互
binder工作流程
1.客户端获取服务端代理对象
2.客户端调用代理对象向服务端发送请求
3.代理对象将用户请求通过binder驱动发送到服务端进程
4.服务端进程处理用户请求,并将结果通过binder驱动发挥给代理对象
5.客户端收到返回结果
Binder的内存拷贝过程
相比其他的IPC通信,比如消息机制、共享内存、管道、信号量等,Binder仅需一次内存拷贝,即可让目标进程读取到更新数据,同共享内存一样相当高效,其他的IPC通信机制大多需要2次内存拷贝。Binder内存拷贝的原理为:进程A为Binder客户端,在IPC调用前,需将其用户空间的数据拷贝到Binder驱动的内核空间,由于进程B在打开Binder设备(/dev/binder)时,已将Binder驱动的内核空间映射(mmap)到自己的进程空间,所以进程B可以直接看到Binder驱动内核空间的内容改动
传统IPC机制的通信原理(2次内存拷贝)
1.发送方进程通过系统调用(copy_from_user)将要发送的数据存拷贝到内核缓存区中。
2.接收方开辟一段内存空间,内核通过系统调用(copy_to_user)将内核缓存区中的数据拷贝到接收方的内存缓存区。
种传统IPC机制存在2个问题:
1.需要进行2次数据拷贝,第1次是从发送方用户空间拷贝到内核缓存区,第2次是从内核缓存区拷贝到接收方用户空间。
2.接收方进程不知道事先要分配多大的空间来接收数据,可能存在空间上的浪费。
Binder驱动的执行过程
binder_init
- 分配内存
- 初始化设备
- 放入链表 binder_devices
binder_open
- 创建binder_proc对象
- 当前进程信息,proc
- filp->private_data = proc;
- 添加到binder_procs链表中
binder_mmap
- 通过用户空间的虚拟内存大小 --- 分配一块内核的虚拟内存
- 分配了一块物理内存 --- 4KB
- 把这块物理内存分别映射到,用户空间的虚拟内存和内核的虚拟内存
注:进程的虚拟内存 --- 4M 驱动定的,1M-8k --- intent 异步 同步
binder_ioctl
读写操作
截屏2021-07-15 上午8.01.57.png
网友评论