android binder 面试

机制原理

参考

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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值