须要学会Binder的基本使用和原理,须要的知识点有:java
Linux进程和空间的概念android
虚拟地址概念git
经常使用IPC,他们的基本流程和Binder的区别缓存
C/S架构基本思路,也就是Binder驱动,ServerManager,Client和Server这四个概念。安全
AIDL以及支持的数据类型,包括Parcelable等,以及编写服务器
Service(Android的四大组件之一),Binder等几个具体的java类使用。网络
如下是本身的一些Binder学习总结,若有侵权请联系删除。架构
在Linux系统中,进程是分配给应用程序运行的最小描述,即一个应用程序最少有一个进程,而一个进程之间又最少有一个线程,进程给应用程序分配内存空间。ide
空间:在Linux中,为了保持系统的稳定性,分为内核空间和用户空间,内核空间的权限最高,用户空间的权限最低。好比读写文件,网络请求就是在内核空间中进行的。学习
在Linux中,存在着进程隔离,也就是进程A没法直接访问进程B的数据,他们之间各自具备独立的内存。假如他们须要进行通讯,就必须经过IPC来实现,主要是经过两个方法:copy_from_user
和copy_to_user
。
在给应用程序分配内存的时候,对于应用程序来讲,他是一片连续的内存空间,可是实际上,这些内存空间映射到具体的物理内存中是碎片化的不连续的,这个在应用程序看来是连续的空间就是经过虚拟地址实现的。经过虚拟地址,让应用程序看似拥有连续的内存空间,从而映射到具体的物理内存中。
好比,在32位系统中,能够寻址的空间长度是2的32次方,也就是4GB。
包括:
共享内存
消息管道
Socket
信号量
这些是经常使用的IPC方法,通常而言,他们会经历两次的数据copy,共享内存除外。
第一次是发送方将数据经过copy_from_user
拷贝到内核空间中,这是第一次。而后,接收方在本身的内存空间中,分配缓存区,经过copy_to_user
方法把内核空间的数据复制到本身进行读取。
以下图:
对于Android系统而言,上面的几种方式都不太适合,首先对于两次的数据拷贝,存在的问题是:
copy次数多耗费时间
接收方不知道须要分配多大的内存接受数据,或者是须要提早通知接受方分配而耗费时间。
对于共享内存,虽然它无需copy可是较为难以控制,安全性方面较差。
那么Binder在这方面具备什么优点呢?
Binder是只须要一次数据copy,仅低于共享内存。
他基于C/S架构,职责分离又相互独立,稳定性更好。
在安全性方面,传统的IPC接收方没法获取对方可靠的进程PId,从而没法鉴别对方身份。可是在Android中,他会为每个安装好的App分配一个本身的UID,从而作到能够鉴别身份。
因此Binder是Android系统进行IPC采用的手段。那么Binder为何只是能够一次数据拷贝就好了呢?
这个就是利用虚拟内存了。Binder借助内存映射,在内核空间
和接收方的用户空间
的数据缓存区作了一层内存映射。也就是说,在发送方将数据拷贝到内存空间的时候,内核空间的这部分地址同时也会被映射到接收方的内存缓存中,这样子,就少了一次从内和空间拷贝到用户空间。
以下图:
在Binder中,有四个概念,Binder驱动,ServerManager,Client以及Server,这四个部分组成了BinderC/S架构。
他跟一次网络请求很类似:Client经过域名发起请求,经过DNS域名解析器解析具体的ip地址,而后再经过路由转发到具体的Server,再而后Server将请求结果经过路由转发回Client。
在Binder的IPC中,有以下几个部分:
Binder驱动是一种虚拟的字符设备,注册在/dev/bindr中,其中定义了一套Binder通讯协议,负责创建进程间Binder通讯,提供了数据包在进程之间传递的底层支持。
他的角色相似路由,他是提供进程间通讯的底层支持。负责将Client端的请求转发到Server,并将Server的数据返回给Client。
2 ServerManager
他的做用相似DNS服务器,负责将Client请求的Server的Binder描述转化为具体的Server地址,以便Binder驱动将Client的请求转达到Server。当Server须要提供服务的时候,他必须先向ServerManager注册,这样子,ServerManager中,就存有一份相似key-value的数据,保存了一份Server的Binder字符名称和Binder引用的映射以便Client能够找到。
Client的做用是发起请求,经过Binder向ServerManager发起请求获取Server的具体地址,而后交由Binder驱动转发。
Server假如须要对外提供服务,他就须要先将本身注册到ServerManager中,以便被解析出来。Server在响应请求以后,就将数据经过Binder驱动再次将数据传递会Client。
这就是一次完整的IPC调用。
还有一个问题就是ServerManager的产生,由于Client/Server都是须要经过Binder与ServerManager进行通讯的,那么这个ServerManager是如何产生的呢?
在Android系统启动以后,会建立一个名词为servermanager的进程,能够查看ZygoteInit
文件,在里面的main方法中,调用Zygote
的forkSystemServer
产生。它经过一个约定的命令BINDERSERVER_MGR向Binder驱动注册,申请成为ServerManager。Binder驱动会自动为ServerManager建立一个Binder实体
这个Binder实体的引用在全部的Client中都是0,也就是说各个Client经过0这个引用就能够与ServerManager进行通讯。
上面是咱们的IPC过程,在这个过程当中,Client须要获取到Server端的Binder引用,那么这个引用是真正的Server引用吗,他是如何实现的呢,A进程并没有法直接获取B进程的对象。这个就是须要经过Binder的代理机制实现。
咱们在Client端,向ServerManager获取具体的Server端的Binder引用的时候,会首先进过Binder驱动,Binder驱动它并不会把真正的Server的Bind人引用返回给Client端,而是返回一个代理的java对象,该对象具备跟Server端的Binder引用相同的方法签名,这个对象为ProxyObject,他具备跟Server的Binder实例同样的方法,只是这些方法并无Server端的能力,这个ProxyObject的能力是能够经过Binder驱动,正在实现对Server的Binder进行调用,从而完成数据传递。
好比,当Binder驱动接受到Client进程的请求,就去ServerManager中查询,在ServerManager中查询到具体的Server具体以后,就建立一个Server端的Binder对象的ProxyObject,而且将该ProxyObject返回给Client 。而后Client就经过ProxyObject调用其中的方法,ProxyObject的方法再去调用Binder驱动,这个Binder驱动就去Server进程中,调用具体的Server进程的具体的Binder对象的方法,而后再经过Binder驱动返回数据给Client。
以下图
上面咱们大概梳理了Binder调用的总体流程,知道Binder的大概原理。在Android中,是经过AIDL这一描述性接口语言实现的。
什么是AIDL:Android 接口定义语言 (AIDL)
关于如何使用AIDL将在下一篇文章在作详细使用。
关于Binder,做为应用开发者你须要知道的所有(同时也是本文的文章图片来源)