Binder是什么?
Binder就是Android中的血管,在Android中,我们所使用Activity、Service等组件都需要和AMS(system_server)通信,这种跨进程的通信都是通过Binder完成
机制:Binder是一种进程间通信机制;
驱动:Binder是一个虚拟物理设备驱动
应用层Binder是一个能发起通信的Java类
Framework/Native:Binder连接了Client、Server、ServiceManager和Binder驱动程序,形成一套C/S的通信架构。

Binder是基于OpenBinder,谷歌的一个内部项目所设计的,在Android中落地出来。
程序中的多进程:
虚拟机分配给各个进程的运行内存是有限的,LMK(Low Memory Killer)会优先回收对系统资源的占用多的进程。
使用多进程我们可以:
突破进程内存限制,如图库占用内存多;
功能稳定性:独立的通信进程保持长连接的稳定行;
规避系统内存泄漏:独立的webview进程隔绝内存泄漏导致的问题;
隔离风险:对于不稳定的功能放到独立进程,避免导致主进程崩溃。
LMK机制:当我们的内存紧张的时候去负责有限杀掉同级内存所占用比较多的进程。
Android中的webview内存泄漏问题,一直有,因为webview是Android Framework给提供的,我们也解决不聊,Android也没有解决,那我们可以将webview放在单独的一个进程当中。
Binder有什么优势?

内存的划分:
内存被操作系统划分为两块:用户空间和内核空间,用户空间是用户程序代码运行的地方,内核空间是内核代码运行的地方,为了安全,它们是隔离开来的,即使用户的程序崩溃了,内核也不受影响

一般的进程通信,把用户空间的一部分数据拷贝到内核空间去,那就有办法完成这种数据拷贝,然后再从内核拷贝到进程2的去。
syscall:系统调用Linux操作系统提供的API
copy_from_user 从用户空间拷贝数据
copy_to_user 把数据拷贝给用户空间
Socket:internet socket(TCP/IP)
unix domain socket(内部)
unix domain socket :用这个去完成进程间通信,将会更加地有效率,因为它不需要像internet socket那样经过网络协议站,不需要打包 拆包,不需要去计算校验和维护序列号,只要将我们应用层的这个数据从一个进程拷贝到另一个进程里面去就可以了。
对比其他进程通信:
管道pipe:handler就用到了管道机制,结合了管道+epoll,使用管道来实现线程状态的管理,handler帮我们进行了线程的通信。
AB线程通信,A线程向管道写数据,管道中有了数据就会唤醒B线程来处理消息,从而来完成跨进程的通信。
共享内存:Facebook 的Freso(专业的图像框架)、MMKV匿名共享内存
信号量:腾讯的Matix,爱奇艺的XCrash,友盟的amo工具,里面都是运用到信号机制,来完成ANR的监控,信号量类似于广播。

传统的进程通信方式:

从安全性上来说,其他进程通信 AB进程,A进程要跟B进程通信,B进程要跟A进程通信,尼玛AB进程为了安全性,我们必须告知对方身份,A跟B通信,A就要告知B是哪个进程跟它通信,要把自己的身份告诉别人。举个例子,客户客户端要去访问服务端,客户端就要把这个身份告诉服务端,就像做登录功能一样,登录就是把用户的身份告诉服务端你是哪个用户。为什么说共享内存和socket不安全呢,就是在于这个身份,比如在进程当中,我们标识一个进程身份是pid,每个进程都会有一个pid,那么AB进程通信就要把各自的pid发给对方,这样对方才能确认我的身份,但是问题来了,客户端告知服务端的这个身份不可靠,很容易被伪造身份,服务器区分不了由客户端主动发过去的身份标识,多进程中没有密码这么一说。
Binder是在内核中获取pid,放入数据包中,这么做安全,不能伪造,除非改ROM。
Binder更多用在system_server进程,AMS,PMS,WMS这种系统服务进程,跟我们的上层App进程来通信的一套机制,更多的是面向对象,而不像其他的通信机制,是面向过程的,那么综合几点考虑,Binder就成了Android系统中的不二选择。、
Binder为什么只需拷贝一次?(快递柜)

快递柜的存在就是给我们快递系统降低成本,提高效率的,那么快递系统就好比作Binder机制,Binder机制呢,就是利用了这种快递柜,A要把自己的包裹送给B,包裹在A进程中,要打电话给快递,快递会派一个收件员上门收件,神门收件就是把包裹拷贝一份,拷贝到我们的内核中来,拿到快递系统中来,然后快递系统来传输数据的时候,以前是需要有一个派件员把我们的数据派给我们的B的,现在有了快递柜了,快递系统只要把数据放到快递柜里面去,不需要有派件员去派件了,B就可以随时在快递柜中去取数据,所以这个快递柜就是B和快递系统所共有的一块内存区域,把数据放到快递柜就相当于放到了B进程的内部空间。


B进程的用户空间中,它所有的这些虚拟内存跟内核空间的虚拟内存是有内存隔离的。这时候Binder做了一件事情,将内核空间的一块内存空间区域(内存--这里指虚拟内存,虚拟内存都会对应到一块物理内存),Binder机制就利用这个将内核空间的一块虚拟内存映射到一块指定的物理内存地址中,用户空间当中,它也去生命一块虚拟内存区域,将它也对应到这块物理内存地址,那么这时候,用户空间的某一块内存区域跟内核空间的某一块内存区域,他们对应的是同一份物理地址,同一份物理内存,这时候,我往内核空间当中去放数据,实际上是把数据放到了共同的这块地址上,那么B进程要拿这个数据,B用户空间就可以直接从公共区域中拿数据,直接就拿到了内核空间放到这公共区域的数据,这个过程就不需要拷贝了。所以只进行了一次拷贝。
MMAP的原理是什么?
MMAP叫做内存映射。
先来看看传统的IO,譬如FileInputStream,FileOutputStream。

写文件流畅:
1.调用write,告诉内核需要写入数据的开始地址与长度
2.内核将数据拷贝到内核页缓存
3.由系统调用,将数据拷贝到磁盘,完成写入
要完成文件的读写操作,只能由内核去完成,所以当我们程序当中有一段数据要写到某一个文件里面去,那我们必须是去把这个数据拷贝到内核,然后内核再通过DMA拷贝,把数据拷贝到文件,一次是由用户空间拷贝到内核空间,这是CPU参与的拷贝,一次是把数据拷贝到我们的磁盘缓冲区,这是由DMA参与的拷贝,两次拷贝。
MMAP
Linux通过将一个虚拟内存区域与文件描述符关联起来,以初始化这个虚拟内存区域的内存区域的内容,这个过程称为内存映射(memory mapping)

对文件进行mmap会在进程的虚拟内存分配地址空间,创建映射关系。
1.在用户空间调用mmap后,会在当前进程的虚拟空间中分配一段区域并使用vm-area-struct(vma)结构记录这个区域。
2.通过文件描述符链接到内核的文件结构提,每个文件结构体维护着打开文件的相关信息。
3.通过文件结构体file*定位到了文件,建立页表,将文件对应的物理地址和vma映射关联。
4.进程的读或写操作访问虚拟地址空间这一段映射地址,但是目前只建立了地址映射,真正的硬盘数据还没拷贝到内存中,因此引发缺页异常出发将文件内容拷贝到与vma(虚拟内存)关联的物理内存。
为什么不直接映射到同一块物理内存?
要是这么干的话,就跟共享内存一样了,那就需要用户去维护这一个多进程的数据同步问题。自己去处理同步是很麻烦的,而且保证不了处理的稳定性。
应用的启动
zygote fork一个新的进程作为我们的应用进程,然后执行我们的RunTimeInit.java,里面它去给我们虚拟机的初始化,然后执行到onZygoteInit(),里面会创建一个ProcessState,这代表了我们的进程,每个进程都有一个,也只有一个ProcessState,在里面会进行Binder的初始化,Binder的准备,Binder的准备是怎么准备的?它就是给我们去完成了mmap内存映射,看到self(),new了一个ProcessState对象,传入“/dev/binder”,这就是所谓的binder虚拟驱动然后找到构造方法,open_driver打开驱动,方法体里面,调用了一个api,mmapapi,映射binder驱动,提供一块虚拟内存空间来接受Binder的数据,这就是将我们的程序在初始化的时候去跟我们的一块物理内存空间去进行映射,得到了一个内存区域,这个内存区域跟Binder的虚拟驱动映射好的,那么在内核立案呢?同样页会去跟这一块Binder的虚拟驱动进行映射,那么mmap映射完之后,就完成了用户空间的一块虚拟内存跟内核空间的一块虚拟内存其实指定的同一块内存的这个操作。
所以mmp就是让我们去完成这种内存映射的,mmap做的事情非常简单,就是帮我们建立好一块指定的虚拟内存跟指定的物理内存的一个映射。其实在Binder之外在很多技术当中也有利用到mmap,例如:
腾讯的mars:https://github.com/tencent/mars
美团的Logan:https://github.com/Meituan-Dianping/Logan
爱奇艺的xCrash:https://github.com/iqiyi/xCrash
Logan对日志协议数据进行格式化处理,针对大日志的分片处理,引入了MMAP机制解决了日志丢失问题,使用AES进行日志加密确保日志安全性。 为了节约用户手机空间大小,日志文件默认只保留最近7天的日志,过期会自动删除。在设备上Logan将日志保存在应用自己的缓存目录中。(mmap: 是一种内存映射文件的方法,它将一个文件映射到进程的地址空间中,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上)
MMAP的优势?
MMAP对文件的读写操作只需要从磁盘到用户主存的一次数据拷贝过程,减少了数据拷贝次数,提高了文件操作效率。
MMAP使用逻辑内存对磁盘进行映射,操作内存就相当于操作文件,不需要开启线程操作MMAP的熟读和操作内存的速度意义快。
Binder机制是怎么跨进程的?
通过把数据发送方的数据拷贝到内核当中来,然后Binder机制说白了就是把数据放到了一个内存区域,这个内存区域特殊在于与数据接收方的用户空间的内存区域是映射到了同一份物理内存,所以这时候我们的数据接收方就能从自己的内存区域拿到我们Binder发过来的数据,就完成了整个通信过程。
网友评论