Binder到底是什么?Binder通信到底是怎么实现的?脱离复杂的Android Framework代码,用最简单的方式来理解下什么是Binder通信。
关于IPC通信
在Linux系统中,正常运行的两个进程A和B,它们之间如果要进行数据的通信,需要借助Linux的IPC通信机制,如消息,共享内存,信号量等。也就是说在Linux系统中,如果要让两个进程进行通信,一定要通过IPC机制。而Android系统是建立在Linux系统基础之上的,因此Android的两个进程之间的通信,也必然要通过IPC机制。原来的工作方式是这样的:
关于RPC通信
在Android系统时,有时进程A需要访问进程B的接口,假设进程B的主要功能是负责LED灯的开与关,即进程B提供LEDOpen(), 或LEDClose(), 但是进程A无法,并且也没有权限去直接调用进程B的这两个接口。于是,有一个解决方案就是,进程A封装一些参数,比如int which(哪个LED), int state(灯的状态:1开/0关),进程A把进程B调用LEDOpen()或LEDClose()的关键的信息参数封装了一下,然后通过Linux系统的IPC机制,将封装好的参数发送给进程B, 进程B拿到这些参数后,进行解析,得到具体的参数int which(哪个LED), int state(灯的状态:1开/0关),然后调用相应的API, 实现了真正的LED开关操作。这整个过程称为RPC.
下面用一幅图来表示这个过程:
这样就可以给人一种感觉,好像是进程A在直接调用服务接口,而以上的内容本质上就是Binder通信的核心。
关于Binder通信
进一步思考,对于通信,一般都涉及三个因素:发送方,接收方和发送内容。对于上面的例子中发送方是进程A,接收方是进程B, 发送的内容就是封装的数据。 但是身为发送方的进程A,怎么知道接收方B,换句话说,进程A怎么找到进程b,或者进程B在进程A中是以什么样的方式存在呢?这时就一定要引入第三者。
现在做个约定,发送方称为Client客户端 ,接收方称为Server服务端,因为接收方是为发送方提供服务接口的,它拥有发送方所需要的功能或处理函数。将引入的第三者称之为ServiceManager.于是就有了下面这张图:
第一步:Server服务端在为他们提供服务之前,需要向服务管理中心即ServiceManager注册自己
第二步:ServiceManager(简称SM)注册成功后,将Server的信息保存在一张表中。
第三步:Client客户端要使用Server服务端提供服务之前,需要先向SM查找Server服务端,获得Server端的使用凭证,类似一个Handle
第四步:SM收到查询请求后,查到到信息表,找到Server服务端后,将Server的句柄返回给Client客户端。
第五步:Client客户端开始打包数据。
第六步:发送数据(通过Binder驱动)
第七步:Server服务端收到数据,开始解析数据
第八步:Server根据得到的数据进行函数调用
第九步:Server端将函数的执行结果返回给Client客户端,客户端后收到,根据执行结果进行下一步处理。
关于参数打包
上面描述的是Binder通信的全过程,需要有个第三方中介来保存Server的信息,借助第三方中介提供的信息,客户端Client可以轻松获得Server提供的服务handle,这个handler可以代表Server的实体 ,通过它,就可以实现与Server的通信了,但是通信之前,在Client端需要做一个工作,数据的打包,数据打包有什么讲究?
需要搞清楚以下两个问题:
(1) Server提供哪几个服务(函数),Server怎么知道Client要调用的是哪个函数?
解决:可以对函数进行编号,称为code, 如LEDOpen()编为code = 1, LEDClose()编为code=2
(2) Client要传哪 些参数过去?参数怎么传?
解决:可以将参数打包放到buffer中,双方约定好以client打包的方式逆向操作去解析。
Server收到数据包后,解析出code,就能知晓要调用哪个函数,解析出参数后,这个就是函数调用的实参。这样一来,Server端就能正常解析并执行函数了,这样就完成了一次完整的Binder通信过程。