第5章 Binder在Native框架层的实现
Android使用Linux的进程管理机制,以进程为单位分配虚拟地址空间。为了安全考虑,一个进程禁止直接与其他进程交互,这样不同进程之间是相互隔离的(Process Isolation)。如果进程间需要通信,必须通过Android的Linux内核提供的进程间通信(Inter Process Communication, IPC)机制实现间接通信。Linux使用的进程间通信方式有很多种,例如第4章中使用的Socket,另外还有Signal(信号)、Pipe(管道)、Message Queue(消息队列)、Semaphore(信号量)、Shared Memory(共享内存)等。但是,这些IPC机制要么效率低下,要么不适合封装给上层复用,所以它们并没有在Android中大规模使用,取而代之的是使用Binder。
从Android体系结构的角度看,Binder是Android对Linux内核层的一个扩展,属于一个字符设备驱动,Android便是通过这个驱动程序实现不同进程之间的间接通信。Android通过对Binder封装,提供了一套Binder操作的框架,便于上层使用,这样Binder的概念便不仅仅是一个驱动,而是被拓展为一种架构。通过这种架构,Binder实际上成为“框架的框架”,Binder框架分成Native层和Java层两部分,本章分析Native层的Binder实现。
5.1 Binder与C/S体系结构概述
Android吸收了组件化的设计思想,将大量的核心功能放在不同的Service组件中实现,需要使用这些功能的其他组件,可以通过系统提供的接口访问这些Service。提供服务的组件和使用服务的组件可以运行在不同的进程中,通常把Service组件所在的进程称为Server进程,把使用Service的组件所在进程称为Client进程,这其实是一个C/S体系结构。Binder便为这种体系结构提供IPC通信功能。C/S体系结构通常由以下部分组成:
用户端(Client):是C/S体系结构中使用Server端提供的Service的一方。
服务端(Server):是C/S体系结构中为Client端提供Service的一方。
服务代理(Proxy):位于Client端,提供访问服务的接口。其主要作用是屏蔽用户端与Server端通信的细节,如对请求数据的序列化和对响应数据的反序列化、通信协议的处理等。
服务存根(Stub):位于Server端,屏蔽了Proxy与Server端通信的细节,如对Client端Proxy请求数据的反序列化和对Server端响应数据的序列化、通信协议的封装和处理、匹配Client端调用Service的具体方法,因此,Stub相当于Service的代理。
服务(Service):运行于Server端,提供具体的功能处理Client端的请求。
通信协议:Client端和Server端可以运行于不同的进程中,甚至可以运行于不同的主机中,因此需要提供远程通信功能。在Android中,主要使用Binder作为Client端与Server端通信的协议。
为了简化Client使用Service的流程,在Android的C/S体系结构中增加了一个额外的组件servicemanager,该组件提供了Service注册和Service检索功能。Service在启动过程中将自身信息注册到servicemanager中,因此servicemanager中维护了一个Service信息的列表。这样Client要使用服务时,只需向servicemanager提供所需Service的名字便可获取Service信息。servicemanager是由init启动的进程,其本身也是一个Server。
注意 涉及Binder相关内容,本书都将Service所在进程称为Server,这是C/S体系结构的惯例。Service是Server中运行的组件,一个Server中可以运行多个Service。