Binder相关知识

1.为什么是binder

1.1 Android系统是基于Linux内核实现的,Linux本身有管道、消息队列、共享内存和套接字(Socket)等等进程间通信方式,为什么还要弄一套Binder呢?

1.1.1 性能角度

管道、消息队列、Socket实现一次进程通信都需要2次内存拷贝,效率太低;共享内存虽然不需要拷贝内存,但管理复杂;Binder只需要一次内存拷贝,从性能角度来看,低于共享内存方式,优于其它方式。

1.1.2 安全性考虑

传统的IPC机制没有安全措施,接收方无法获得对方可靠的进程ID或用户ID,完全靠上层的协议来保护,比如Socket通信的IP地址是客户端填入的,很可能被恶意程序篡改。Android作为面向终端用户的开源平台,应用市场中有海量的应用供用户选择,因此安全性极为重要。

Android系统为每个已安装的App都分配了用户ID(UID),UID是鉴别进程身份的重要标识,通过UID可以进行一系列的权限校验。另一方面 ,传统IPC的接入点是开放的,任何程序都可以根据协议进行访问,无法阻止恶意程序的访问,Android需要一种基于C/S架构的IPC机制,Server端需要能够对Client的请求进行身份校验,来保证数据的安全性。

1.2.4 内核模块/驱动

传统的IPC机制都是通过内核来支持的,Binder也一样,有一个运行在内核中的Binder驱动程序负责进程之间Binder的通信。Binder驱动是一种虚拟的字符设备,注册在/dev/binder中,其定义了一套Binder通信协议,负责建立进程间的Binder通信,提供了数据包在进程之间传递的一系列底层支持。应用进程访问Binder驱动也是通过系统调用实现的。

2.binder基本原理

在Binder机制中,定义了4个角色:Client、Server、Binder驱动和ServiceManager。

  • Binder驱动:类似网络通信中的路由器,负责将Client的请求转发到具体的Server中执行,并将Server返回的数据传回给Client。

  • ServiceManager:类似网络通信中的DNS服务器,负责将Client请求的Binder描述符转化为具体的Server地址,以便Binder驱动能够转发给具体的Server。Server如需提供Binder服务,需要向ServiceManager注册。

具体的通信过程是这样的:

  1. Server向ServiceManager注册

    Server通过Binder驱动向ServiceManager注册,声明可以对外提供服务。ServiceManager中会保留一份映射表:名字为zhangsan的Server对应的Binder引用是0x12345。

  2. Client向ServiceManager请求Server的Binder引用

    Client想要请求Server的数据时,需要先通过Binder驱动向ServiceManager请求Server的Binder引用:我要向名字为zhangsan的Server通信,请告诉我Server的Binder引用。

  3. 向具体的Server发送请求

    Client拿到这个Binder引用后,就可以通过Binder驱动和Server进行通信了。

  4. Server返回结果

    Server响应请求后,需要再次通过Binder驱动将结果返回给Client。

可以看到,Client、Server、ServiceManager之间的通信都是通过Binder驱动作为桥梁的,可见Binder驱动的重要性。

比如一个Server提供add方法,Client实际请求add的流程是这样的:Client先通过Binder驱动向ServiceManager获取Server的Binder引用,这个引用就是一个Java Object,这个Object有一个add方法;Cient拿到这个Object后就可以直接请求add方法了。

实际上Client拿到的Object并不是Server真正的Binder实体,Binder驱动做了一层对象转换,将这个Object包装成了一个代理对象ProxyObject,这个ProxyObject和真正的Binder实体有相同的方法签名,Client通过这个ProxyObject请求add方法时,Binder驱动会自动将请求转发到具体的Binder实体中执行,这就是Binder的代理机制。

由于ProxyObject和真正的Binder实体有相同的方法签名,其实Client并不需要关心是ProxyObject还是真实的Object。

3 Binder的代理机制

通过上面的分析,我们已经知道了Binder的基本通信过程:Client向SerivceManger获取到Server的Binder引用,Client通过Binder引用向Server发起具体请求。

比如一个Server提供add方法,Client实际请求add的流程是这样的:Client先通过Binder驱动向ServiceManager获取Server的Binder引用,这个引用就是一个Java Object,这个Object有一个add方法;Cient拿到这个Object后就可以直接请求add方法了。

 

实际上Client拿到的Object并不是Server真正的Binder实体,Binder驱动做了一层对象转换,将这个Object包装成了一个代理对象ProxyObject,这个ProxyObject和真正的Binder实体有相同的方法签名,Client通过这个ProxyObject请求add方法时,Binder驱动会自动将请求转发到具体的Binder实体中执行,这就是Binder的代理机制。

 

4 对Binder概念的重新理解

经过上面的分析,我们已经大体清楚了Binder机制的基本通信原理,现在回过头来重新梳理下对Binder机制的认识:

总体来说,Binder是基于C/S结构的一种面向对象的IPC机制。包含:Client、Server、Binder驱动和ServiceManager四大组成部分。各组成部分中的Binder含义都有所有不同:

  • 对于Client

    Binder是Server本地对象的一个引用,这个引用实际上是一个代理对象,Client通过这个代理对象来间接访问Server的本地对象;

  • 对于Server

    Binder是提供具体实现的本地对象,需向ServiceManager注册;

  • 对于Binder驱动

    它是连接Client来Server的桥梁,负责将代理对象转化为本地对象,并将Server的执行结果返回给Client。

  • 对于ServiceManager

    它保存了Server Binder字符名称和Binder引用的映射,Client通过它来找到Server的Binder引用。

5 Binder通信的具体流程

Client调用Binder代理对象,Client线程挂起:客户端拿到的实际上是Proxy,调用的A方法当然也是代理中的A方法,其将参数序列化后,调用其成员mRemote成员的transact方法,并且客户端挂起;

Binder代理对象将请求派发给Binder驱动

Proxy中的mRemote成员实际上是BinderProxy,而BinderProxy中的transact方法最终调用于transactNative方法,也就是说Client的请求派发给了Binder驱动来处理。

Binder驱动将请求派发给Server

Binder驱动经过一系列的处理后,将请求派发给了Server,即调用Server本地Binder对象(Stub)的onTransact方法最终在此方法中完成getPid方法的具体调用。在onTransact方法中,根据Proxy中调用transact时传入的方法编号来区别具体要处理的方法。

唤醒Client线程,返回结果

onTransact处理结束后,将结果写入reply并返回至Binder驱动,驱动唤醒挂起的Client线程,并将结果返回。至此,一次跨进程通信完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值