今天说说神秘又常用又多变的Binder~

  • Binder是什么
  • Binder通信过程和原理
  • 在Android中的应用
  • Binder优势

Binder是什么

先借用神书《Android开发艺术探索》中的一段话:

直观的说,Binder是一个类,实现了IBinder接口。

从IPC(Inter-Process Communication,进程间通信)角度来说,Binder是Android中一种跨进程通信方式。

还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder。

从Android FrameWork角度来说,Binder是ServiceManager连接各种Manager(ActivityManager,WindowManager等等)和响应ManagerService的桥梁。

从Android应用层来说,Binder是客户端和服务端进行通信的媒介。

挺多概念的是吧,其实就说了一件事,Binder就是用来进程间通信的,是一种IPC方式。后面所有的解释都是Binder实际应用涉及到的内容。

不管是获取其他的系统服务,亦或是服务端和客户端的通信,都是源于Binder的进程间通信能力。

Binder通信过程和原理

首先,还是看一张图,原图也是出自神书中:

首先要明确的是客户端进程是无法直接操作服务端中的类和方法的,因为不同进程直接是不共享资源的。所以客户端这边操作的只是服务端进程的一个代理对象,也就是一个服务端的类引用,也就是Binder引用。

总体通信流程就是:

  • 客户端通过代理对象向服务器发送请求。
  • 代理对象通过Binder驱动发送到服务器进程
  • 服务器进程处理请求,并通过Binder驱动返回处理结果给代理对象
  • 代理对象将结果返回给客户端。

再看看在我们应用中常常用到的工作模型,上图:

这就是在应用层面我们常用的工作模型,通过ServiceManager去获取各种系统进程服务。这里的通信过程如下(详细流程也可参考文末链接):

  • 服务端跨进程的类都要继承Binder类,所以也就是服务端对应的Binder实体。这个类并不是实际真实的远程Binder对象,而是一个Binder引用(即服务端的类引用),会在Binder驱动里还要做一次映射。
  • 客户端要调用远程对象函数时,只需要调用Binder引用的方法,一般是transact函数。
  • 然后Binder引用会把数据放入到Client的共享内存,Binder驱动从Client的共享内存中读取数据,根据这些数据找到对应的远程进程的共享内存。
  • 然后把数据拷贝到远程进程的共享内存中,并通知远程进程执行onTransact()函数,这个函数也是属于Binder类。
  • 远程进程Binder对象执行完成后,将得到的写入自己的共享内存中,Binder驱动再将远程进程的共享内存数据拷贝到客户端的共享内存,并唤醒客户端线程。

所以通信过程中比较重要的就是这个服务端的Binder引用,通过它来找到服务端并与之完成通信。

看到这里可能有的人疑惑了,图中线程池怎么没用到啊?

  • 可以从第一张图中看出,Binder线程池位于服务端,它的主要作用就是将每个业务模块的Binder请求统一转发到远程Servie中去执行,从而避免了重复创建Service的过程。也就是服务端只有一个,但是可以处理多个不同客户端的Binder请求。

在Android中的应用

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接口。

Binder优势

在Linux中,进程通信的方式肯定不止Binder这一种,还有以下这些:

管道(Pipe)
信号(Signal)
消息队列(Message)
共享内存(Share Memory)
套接字(Socket)
Binder

Binder在这之后主要有以下优点:

  • 性能高,效率高:传统的IPC(套接字、管道、消息队列)需要拷贝两次内存、Binder只需要拷贝一次内存、共享内存不需要拷贝内存。
  • 安全性好:接收方可以从数据包中获取发送发的进程Id和用户Id,方便验证发送方的身份,其他IPC想要实验只能够主动存入,但是这有可能在发送的过程中被修改。

熟悉Zygote的朋友可能知道,在fork()进程的时候,也就是向Zygote进程发出创建进程的消息的时候,用到的进程间通信方式就不是Binder了,而换成了Socket,这主要是因为fork不允许存在多线程,Binder通讯偏偏就是多线程。

所以具体的情况还是要去具体选择合适的IPC方式。

参考

https://www.cnblogs.com/hustcser/p/10228843.html

拜拜

有一起学习的小伙伴可以关注下️我的公众号——码上积木,每天剖析一个知识点,我们一起积累知识。

最新文章

  1. BZOJ 1923: [Sdoi2010]外星千足虫
  2. Editplus 中将文本换行替换为<p>标签的正则表达式
  3. 安装android studio 出现的路径问题 tools.jar' seems to be not in Android Studio classpath
  4. Java提高学习之Object(3)
  5. 数论F - Strange Way to Express Integers(不互素的的中国剩余定理)
  6. jquery 分页控件2
  7. java 时间
  8. php 日期时间类型带毫秒
  9. 谷歌浏览器扩展程序manifest.json参数详解
  10. 正向代理 vs 反向代理
  11. MySQL中使用连接查询
  12. C++ 的 runtime exception是没有扩展性的
  13. jQuery设置下拉框select 默认选中第一个option
  14. 实效云计算用户组(ECUG) 与 阿里云
  15. 学霸系统UI部分功能规格说明书
  16. ES6 Javascript 实用开发技巧
  17. jquery实现简单瀑布流
  18. 用jQuery的attr()设置option默认选中无效的解决 attr设置属性失效
  19. CLR 显示实现事件 EventSet内部管理一个字典
  20. time stamp in javascript

热门文章

  1. 3. Distributional Reinforcement Learning with Quantile Regression
  2. 在java的多态调用中,new的是哪一个类就是调用的哪个类的方法。
  3. 万字长文深入理解java中的集合-附PDF下载
  4. c++ stl库中的set
  5. 双非本科拿到阿里腾讯字节,分享Java后端路线
  6. NB-IoT的同步信号解析
  7. Learn day4 函数参数\变量\闭包\递归
  8. DevOps 视角的前后端分离与实战
  9. 如何k个一组反转链表
  10. .NetCore操作MongDB简要代码实现