机制原理

参考

https://www.cnblogs.com/qingchen1984/p/5212755.html

https://www.cnblogs.com/baronzhang/p/8784458.html

面试题

1.全面升级Android面试之Binder面试题集

参考:https://blog.csdn.net/lijizhi19950123/article/details/77920054

  • 什么是Binder
  1. 直观来说,Binder是Android中的一个类,它继承了IBinder接口
  2. 从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在linux中没有
  3. 从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager,etc)和相应ManagerService的桥梁
  4. 从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当你bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务
  • 为什么要使用Binder?

在传统的Linux上,我们还是有很多选择可以用来实现进程间通信,如管道、SystemV、Socket等。那么Android为什么不使用这些原有的技术,而是要使开发一种新的叫Binder的进程间通信机制呢?

主要有两个方面的原因:

性能方面
在移动设备上(性能受限制的设备,比如要省电),广泛地使用跨进程通信对通信机制的性能有严格的要求,Binder相对出传统的Socket方式,更加高效。Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,共享内存方式一次内存拷贝都不需要,但实现方式又比较复杂。

安全方面
传统的进程通信方式对于通信双方的身份并没有做出严格的验证,比如Socket通信ip地址是客户端手动填入,很容易进行伪造,而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。

还有一些好处,如实现面象对象的调用方式,在使用Binder时就和调用一个本地实例一样。

  • Binder的线程管理

每个Binder的Server进程会创建很多线程来处理Binder请求,可以简单的理解为创建了一个Binder的线程池吧(虽然实际上并不完全是这样简单的线程管理方式),而真正管理这些线程并不是由这个Server端来管理的,而是由Binder驱动进行管理的。

一个进程的Binder线程数默认最大是16,超过的请求会被阻塞等待空闲的Binder线程。理解这一点的话,你做进程间通信时处理并发问题就会有一个底,比如使用ContentProvider时(又一个使用Binder机制的组件),你就很清楚它的CRUD(创建、检索、更新和删除)方法只能同时有16个线程在跑。

  • Binder运行机制

Binder基于Client-Server通信模式,除了Client端和Server端,还有两角色一起合作完成进程间通信功能。

Binder通信的四个角色:

Client进程:使用服务的进程。

Server进程:提供服务的进程。

ServiceManager进程:ServiceManager的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。

Binder驱动:驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。

初次接触这些概念可能会觉得难于理解,读者可以把四个角色和熟悉的互联网进行类比:Server是服务器,Client是客户终端,ServiceManager是域名服务器(DNS),驱动是路由器。这样类比,你很容易就能理解下图:

  • Binder的工作流程

1 客户端首先获取服务器端的代理对象。所谓的代理对象实际上就是在客户端建立一个服务端的“引用”,该代理对象具有服务端的功能,使其在客户端访问服务端的方法就像访问本地方法一样。

2 客户端通过调用服务器代理对象的方式向服务器端发送请求。

3 代理对象将用户请求通过Binder驱动发送到服务器进程。

4 服务器进程处理用户请求,并通过Binder驱动返回处理结果给客户端的服务器代理对象。

5 客户端收到服务端的返回结果。

  • 实现一个Messenger的步骤

基于消息的进程间通信方式:

服务端进程

需要在服务端创建一个Service来处理客户端的连接请求,同时创建一个Handler并通过它来创建一个Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder即可。

客户端进程

客户端进程中,首先绑定服务端的Service,绑定成功后用服务端返回的IBinder对象创建一个Messenger,通过这个Messenger就可以向服务端发送消息,发送消息的类型为Message对象。如果需要服务端能够回应客户端,就和服务端一样,我们还需要创建一个Handler并创建一个新的Messenger,并把这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数就可以回应客户端。

  • AIDL的工作流程

服务端

服务端首先要创建一个远程Service用来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口即可。

客户端

首先绑定服务端的Service,绑定成功后,将服务端返回的Binder对象转化成AIDL接口所属的类型,接着就可以调用AIDL中的方法了。

AIDL文件支持的数据类型

基本数据类型;

String和CharSequence;

List:只支持ArrayList,里面每个元素都必须被AIDL支持;

Map:只支持HashMap,里面每个元素都必须被AIDL支持,包括key和value;

Parcelable:所有实现了Parcelable接口的对象;

AIDL:所有AIDL接口本身都可以在AIDL文件中使用。

Parcelable和AIDL对象无论是否和当前AIDL文件位于同一个包内,都要显式import进来。
服务端实现需要注意并发处理,可以借助Copy-On-Write容器
服务端实现监听时,监听存储容器使用RemoteCallbackList,系统专门提供用来删除跨进程listener的接口
AIDL的包结构在服务端和客户端要保持一致,否则出错,因为客户端要反序列化服务端中和AIDL接口相关的所有类,如果类的完整路径不一样的话,就无法成功反序列化。
AIDL调用服务端方法后,会挂起等待,如果服务端进行执行大量耗时操作,会导致客户端ANR。解决方法:客户端调用放在非UI线程即可。

  • Binder对应用开发者的用处

参考
https://blog.csdn.net/universus/article/details/6211589

更多相关文章

  1. 【Android】线程/进程绑定指定CPU核
  2. Service Manager进程启动,睡眠等待在进程proc->wait
  3. Android使用AIDL实现进程间通信
  4. Android实现网易新闻客户端首页效果
  5. Android 彻底退出自己APP 并杀掉所有相关的进程
  6. android客户端向服务器提交请求的中文乱码问题
  7. Android高仿网易新闻客户端之首页
  8. Android翻译:应用程序的生命周期 kill进程
  9. Android 进程管理

随机推荐

  1. SQL SERVER中常用日期函数的具体使用
  2. SQLServer 日期函数大全(小结)
  3. SQLServer2019配置端口号的实现
  4. 解决sql server 数据库,sa用户被锁定的问
  5. sqlserver主键自增的实现示例
  6. Sqlserver创建用户并授权的实现步骤
  7. SQL Server使用脚本实现自动备份的思路详
  8. SQL Server连接查询的实用教程
  9. sqlserver添加sa用户和密码的实现
  10. SQL Server子查询的深入理解