今天说说神秘又经常使用又多变的Binder~html
先借用神书《Android开发艺术探索》中的一段话:java
直观的说,Binder是一个类,实现了IBinder接口。 从IPC(Inter-Process Communication,进程间通讯)角度来讲,Binder是Android中一种跨进程通讯方式。 还能够理解为一种虚拟的物理设备,它的设备驱动是/dev/binder。 从Android FrameWork角度来讲,Binder是ServiceManager链接各类Manager(ActivityManager,WindowManager等等)和响应ManagerService的桥梁。 从Android应用层来讲,Binder是客户端和服务端进行通讯的媒介。
挺多概念的是吧,其实就说了一件事,Binder
就是用来进程间通讯的,是一种IPC
方式。后面全部的解释都是Binder
实际应用涉及到的内容。android
不论是获取其余的系统服务,亦或是服务端和客户端的通讯,都是源于Binder
的进程间通讯能力。安全
首先,仍是看一张图,原图也是出自神书中:服务器
首先要明确的是客户端进程是没法直接操做服务端中的类和方法的,由于不一样进程直接是不共享资源的。因此客户端这边操做的只是服务端进程的一个代理对象,也就是一个服务端的类引用,也就是Binder
引用。多线程
整体通讯流程
就是:函数
Binder
驱动发送到服务器进程Binder
驱动返回处理结果给代理对象再看看在咱们应用中经常用到的工做模型
,上图:工具
这就是在应用层面咱们经常使用的工做模型,经过ServiceManager
去获取各类系统进程服务。这里的通讯过程以下(详细流程也可参考文末连接):性能
Binder
类,因此也就是服务端对应的Binder
实体。这个类并非实际真实的远程Binder
对象,而是一个Binder
引用(即服务端的类引用),会在Binder
驱动里还要作一次映射。Binder
引用的方法,通常是transact
函数。Binder
驱动从Client的共享内存中读取数据,根据这些数据找到对应的远程进程的共享内存。Binder
类。Binder
对象执行完成后,将获得的写入本身的共享内存中,Binder驱动再将远程进程的共享内存数据拷贝到客户端的共享内存,并唤醒客户端线程。因此通讯过程当中比较重要的就是这个服务端的Binder引用
,经过它来找到服务端并与之完成通讯。学习
看到这里可能有的人疑惑了,图中线程池
怎么没用到啊?
Binder线程池
位于服务端,它的主要做用就是将每一个业务模块的Binder请求统一转发到远程Servie中去执行,从而避免了重复建立Service的过程。也就是服务端只有一个,可是能够处理多个不一样客户端的Binder
请求。Binder在Android中的应用除了刚才的ServiceManager
,你还想到了什么呢?
getSystemService
获取的服务,内部也就是经过ServiceManager
。例如四大组件的启动调度等工做,就是经过Binder机制传递给ActivityManagerService,再反馈给Zygote
。而咱们本身平时应用中获取服务也是经过getSystemService(getApplication().WINDOW_SERVICE)
代码获取。AIDL(Android Interface definition language)
。例如咱们定义一个IServer.aidl文件,aidl工具会自动生成一个IServer.java的java接口类(包含Stub,Proxy等内部类)。bindService
绑定后台服务进程时,onServiceConnected(ComponentName name, IBinder service)传回IBinder对象,而且能够经过IServer.Stub.asInterface(service)获取IServer的内部类Proxy的对象,其实现了IServer接口。在Linux中,进程通讯的方式确定不止Binder这一种,还有如下这些:
管道(Pipe) 信号(Signal) 消息队列(Message) 共享内存(Share Memory) 套接字(Socket) Binder
而Binder
在这以后主要有如下优势:
性能高,效率高
:传统的IPC(套接字、管道、消息队列)须要拷贝两次内存、Binder只须要拷贝一次内存、共享内存不须要拷贝内存。安全性好
:接收方能够从数据包中获取发送发的进程Id和用户Id,方便验证发送方的身份,其余IPC想要实验只可以主动存入,可是这有可能在发送的过程当中被修改。熟悉Zygote
的朋友可能知道,在fork()进程的时候,也就是向Zygote进程发出建立进程的消息的时候,用到的进程间通讯方式就不是Binder了,而换成了Socket,这主要是由于fork不容许存在多线程,Binder
通信恰恰就是多线程。
因此具体的状况仍是要去具体选择合适的IPC方式。
http://www.javashuo.com/article/p-nfrqcdjw-nw.html
有一块儿学习的小伙伴能够关注下❤️个人公众号——码上积木,天天剖析一个知识点,咱们一块儿积累知识。