Binder总结篇1-Binder原理
需要学会Binder的基本使用和原理,需要的知识点有:
-
Linux进程和空间的概念
-
虚拟地址概念
-
常用IPC,他们的基本流程和Binder的区别
-
C/S架构基本思路,也就是Binder驱动,ServerManager,Client和Server这四个概念。
-
AIDL以及支持的数据类型,包括Parcelable等,以及编写
-
Service(Android的四大组件之一),Binder等几个具体的java类使用。
以下是自己的一些Binder学习总结,如有侵权请联系删除。
Linux的进程和空间的概念
在Linux系统中,进程是分配给应用程序运行的最小描述,即一个应用程序最少有一个进程,而一个进程之间又最少有一个线程,进程给应用程序分配内存空间。
空间:在Linux中,为了保持系统的稳定性,分为内核空间和用户空间,内核空间的权限最高,用户空间的权限最低。比如读写文件,网络请求就是在内核空间中进行的。
在Linux中,存在着进程隔离,也就是进程A无法直接访问进程B的数据,他们之间各自具有独立的内存。假如他们需要进行通信,就必须通过IPC来实现,主要是通过两个方法:
copy_from_user
和
copy_to_user
。
虚拟地址
在给应用程序分配内存的时候,对于应用程序来说,他是一片连续的内存空间,但是实际上,这些内存空间映射到具体的物理内存中是碎片化的不连续的,这个在应用程序看来是连续的空间就是通过虚拟地址实现的。通过虚拟地址,让应用程序看似拥有连续的内存空间,从而映射到具体的物理内存中。
比如,在32位系统中,可以寻址的空间长度是2的32次方,也就是4GB。
传统IPC
包括:
-
共享内存
-
消息管道
-
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中,有四个概念,Binder驱动,ServerManager,Client以及Server,这四个部分组成了BinderC/S架构。
他跟一次网络请求很相似:Client通过域名发起请求,通过DNS域名解析器解析具体的ip地址,然后再通过路由转发到具体的Server,再然后Server将请求结果通过路由转发回Client。
在Binder的IPC中,有如下几个部分:
- Binder驱动
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
Client的作用是发起请求,通过Binder向ServerManager发起请求获取Server的具体地址,然后交由Binder驱动转发。
- Server
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实体