Android IPC Binder

来源:互联网 发布:珠海联邦制药知乎 编辑:程序博客网 时间:2024/05/29 16:20

(一)前言

Binder原本是IPC工具,但是在Android中它的主要作用是支持RPC(Remote Procedure Call),使得当前进程调用另一个进程的函数就像调用自身的函数是一样轻松简单。Binder又Service Server(含有Android的服务)、Service Client(使用服务的客户端)、Context Manager(确定服务的位置)、以及Binder Dirver四大部分组成。

Anroid是基于Linux内核的操作平台,Android进程和Linux进程一样,它们只运行在进程固有的虚拟地址空间中。用户代码与相关库运行在用户空间内,而内核空间中运行的代码则运行在内核空间中的各个区域中。并且,进程具有独立的地址空间,单独运行。但是内核空间是被其他用户进程所共享的。那么两个进程是如何相互通信的呢?显然是要经过两个进程共享的内核空间了。从内核的角度看,进程只不过是一个作业单位,虽然那各进程的用户空间相互独立,但运行在内核空间中的任务数据、代码都是批次共享的。
内核与用户空间


(二)使用Binder的原因

  • Binder采用Linux中优秀的内存管理技术,在通过内核空间传递数据时能确保数据的可靠性
  • 由于使用用户空间无法访问的内核空间来交换数据,IPC间的安全问题得到解决

(三)Android Binder Model

服务客户端要通过Binder IPC实现对Service Serverf的foo()函数的调用,Binder Dirver充当中间人的角色,将从服务客户端接收到的Binder IPC数据传递给Service Server。具体过程如图:
这里写图片描述
Binder IPC数据包含调用其他进程函数的信息,是Binder Dirver操作的IPC数据单位。

IPC数据包含函数调用相关的内容,她由待调服务号、待调函数名、Binder协议构成。在Android中服务号用来标记运行中的各个服务,便于区分不同的服务;待调函数名用来指定服务客户端将调用的服务中的函数;Binder 协议是处理进程间IPC数据的约定。如图:
Binder IPC数据
Handler指服务号,用来区分不同服务。RPC代码与RPC数据分别表示的是待调函数与传递的参数,即RPC代码确定数据要传递给服务中的哪个函数,RPC数据是传递给RPC代码所指定函数的参数。Binder协议表示IPC数据的处理办法。


(四)Binder IPC数据传递

Binder Dirver是字符驱动设备,通过调用open()或者ioct1()函数即可访问。如下图,显示了系统调用与Binder Dirver中文件运算符函数之间的连接关系。例如:系统调用open()函数与Binder Dirver的binder_open函数连接在一起。
Binder系统调用
应用程序在通过Binder尝试RPC操作时,会进行open()系统调用,获取Binder Dirver的文件描述符。而后,通过mmap()系统调用,在内核中开辟一块区域,以便存放IPC数据。最后,调用ioct1()函数,将IPC数据作为参数传递给Binder Dirver。


(五)Binder IPC数据流

服务客户端调用Service Server的服务函数的过程。如下图所示:
Binder IPC抽象层

  • 服务层:该层包含一系列提供特定功能的服务函数。服务客户端虚拟调用指定的函数,而实际上调用是由Service Server进行的。
  • PRC层:服务客户端在该层生成用于调用服务函数的RPC代码和RPC数据。Service Server会根据传递过来的RPC代码查找相应的函数,并将RPC数据传递给查找到的函数。
  • IPC层:该层将RPC层生成的RPC代码和RPC数据封装成为Binder IPC数据,以便将它们传递给Binder Dirver。
  • Binder Dirver层:接收来自IPC层的Binder IPC数据,查找包含指定服务的Service Server,并将IPC数据传递给查找到的Service Server。

(六)Binder 协议

Binder协议包含在BinderIPC数据中,它从IPC层传递到Binder Dirver,或者从Binder Dirver传递到IPC层。根据传递方向,Binder协议分为两种,一种是从IPC层传递到Binder Dirver层的“BINDER COMMAND PROTOCAL”,另一种是从Binder Dirver层传递到IPC层的“BINDER RETURN PROTOCAL”。两种协议的区别在于”BINDER COMMAND PROTOCAL”是以BC_打头的,而“BINDER RETURN PROTOCAL”是以BR_打头的。
Binder协议的分类
Binder协议

首先,服务客户端使用BC_TRANSACTION将Binder IPC数据传递给Binder Dirver。Binder Dirver接收IPC数据后,分析其中使用的协议,若是BC_TRANSACTION,则根据IPC数据中的Handler信息查找相应的Service Server。然后Binder Dirver会将协议更改为BR_TRANSACTION协议,并将其插入到IPC数据中,把包含BR_TRANSACTION协议的IPC数据传递到Service Server中。Service Server接收到来自Binder Dirver的IPC数据后,分析其中的协议,若是BR_TRANSACTION,则进一步分析IPC数据,调用服务客户端请求的函数。函数执行完成后会按照逆向过程的将IPC应答数据发送给服务客户端。如图:
Binder协议不同处理


(七)Binder寻址

在Android系统中,有一个Context Manager的特殊进程,它为每个服务分配一个称为Handler的编号,并提供服务的注册、检索等管理功能【Context Manager自身的Handler值被设置为0】。如前所述,Binder Dirver会根据IPC数据中的Handler查找Service Server。为了顺利实现Binder寻址,Service Server必须先把自身服务【传送IPC数据,其中包含RPC代码、RPC数据,并且Handler值设置为0】的访问信息注册到Context Manager。
7.1 服务注册
当Service Server向Context Manager注册自身服务时,Binder Dirver就会进行Binder寻址。Binder Dirver首先查找Handler值为0的Binder结点,Handler值为0的Binder结点是Context Manager,Service Server会将IPC数据传递给Context Manager。然后Binder Dirver会生成一个Binder结点,用来表示Service Server中的服务A,接下来生成Binder结点引用数据,以便Context Manager识别所生成的Binder结点,并将相关结点连接起来。根据生成的顺序引用数据会被编号,这种编号将插入到IPC数据中,传递给Context Manager。Context Manager会根据IPC数据中的服务名称与Binder结点编号,将服务注册到自身的服务目录列表中。如图:
服务注册

7.2 服务检索
当服务注册在Android启动阶段完成后,Context Manager的服务列表、Binder Dirver的Binder结点,以及Service Server中的服务就连接在一起了,注册在Context Manager中的服务就可以被其他进程使用了。服务检索过程描述的是服务客户端在检索服务时进行Binder寻址的整个过程。首先,服务客户端会将包含RPC代码、RPC数据、值为0的Handler的IPC数据经由Binder Dirver传递至Context Manager中。Context Manager接收到IPC数据后,根据IPC数据中包含的所请求的服务名称,在自身持有的服务列表中查找对应的服务编号,将查找到的服务编号发送给Binder Dirver。Binder Dirver将根据传递过来的服务编号查找对应的引用数据,然后在服务客户端生成引用数据,并将其与Context Manager引用数据所指的结点连接起来。连接后的Binder结点与Service Server自身服务的Binder结点相对应。Binder Dirver将根据生成顺序为引用数据编号,并将其传递给服务客户端。服务客户端将指定编号指定为Handler,查找Service Server的Binder结点。
服务检索

7.3 服务使用
最后,服务客户端将接收到的引用数据编号保存到Handler中,把与服务函数相关的RPC代码和RPC数据包含进IPC数据中,发送给Service Server,并调用A中的函数。
服务调用


(八)从进程的角度看服务的使用

服务客户端在使用的时候需经历以下三个阶段,无论使用何种系统服务都要经历以下三个阶段。

  1. 服务注册【Service Server与Context Manager间的IPC】
  2. 服务检索【服务客户端与Context Manager间的IPC】
  3. 服务使用【服务客户端与Service Server间的IPC】

8.1 服务注册
服务注册是指将Service Server中的服务注册到Context Manager的服务列表中。其中涉及到Context Manager和Service Server两个进程,它们的所用如下图:
服务注册阶段
过程如下:
进程服务注册

  1. (1)-(3)首先Context Manager调用open()函数打开Binder Dirver,而后调用mmap函数在内核空间中开辟一块用于接收IPC数据的Buffer,再调用ioct1()函数进入待机状态等待接收IPC数据
  2. (4)-(5)为了注册服务,Service Server先打开Binder Dirver,而后调用mmap()函数确定一块Buffer,用于接收IPC应答数据
  3. (6)Service Server生成IPC数据,IPC数据包含RPC数据、RPC代码和Handler为0三部分
  4. (7)Service Server调用ioct1()函数向Binder Dirver传递数据。而后Binder Dirver将来自Service Server的IPC数据传递给Context Manager
  5. (8)-(9)Context Manager分析IPC数据中的RPC代码,并根据RPC代码调用相应的服务注册函数吗,而后使用RPC数据中的服务名称,将指定的服务注册到服务列表中
  6. (10)服务注册完成后,Context Manager会生成IPC应答数据,并传递给Service Server告知服务已经正常注册,完成Binder IPC循环

8.2 服务检索
服务客户端在使用Service Server的服务时,会向Context Manager请求服务的编号,这一个过程称为服务检索,涉及到的两个进程如下所示:
服务检索阶段
过程如下:
进程服务检索

  1. (1)服务注册完成后,Context Manager进入待机状态,等待接收数据
  2. (2)-(4)为了向Context Manager传递IPC数据,服务客户端大陆开Binder Dirver,而后调用mmap()函数准备一块Buffer用于接收IPC应答数据。服务客户端生成IPC数据【Handler值为0】
  3. (5)服务客户端调用ioct1()函数向Binder Dirver传递IPC数据。Binder Dirver根据IPC数据中的Handler将IPC数据传递给Context Manager
  4. (6)-(8)Context Manager分析接收到的IPC数据,根据RPC代码,调用服务检索函数。相关函数根据RPC数据中的服务名称在服务列表中检索服务,查找到服务Binder结点编号。Context Manager将查找到的Binder结点编号插入到IPC应答数据中,传递给服务客户端
  5. 服务客户端接收IPC应答数据,获得指定服务的Binder结点
  6. (9)服务客户端接收IPC应答数据,获得指定服务的Binder结点编号

8.3 服务使用
在服务的使用阶段,服务客户端将实际使用的Service Server的服务。在此过程中,涉及到两个进程。如图:
服务使用阶段
过程如下:
进程服务使用

  1. (1)如Context Manager一样,Service Server也会进入到待机状态,等待接收IPC数据。并且当处理完接收的IPC数据后,它将再次进入到待机状态,等待接收新的IPC数据
  2. (2)-(3)为了使用服务,服务客户端首先生成IPC数据,IPC数据由RPC代码、RPC数据、Handler组成。然后调用ioct1()函数,将IPC数据传递给Binder Dirver。最后Binder Dirver根据IPC数据中的Handler把IPC数据传递给Service Server
  3. (4)-(5)Service Server 分析IPC数据中的RPC代码,根据RPC代码调用服务函数。IPC数据中包含的RPC数据类似于函数的参数,在函数内部使用。当指定的服务函数执行完毕后,Service Server会生成IPC应答数据,其中包含着Binder结点编号,而后将IPC应答数据发送到服务客户端,告知服务函数已经执行完毕
  4. (6)服务客户端接收IPC应答数据,并进行处理

(九)Context Manager

Context Manager,管理服务的注册和检索,采用C语言编写以便使其与Binder Dirver紧密衔接。它先于Service Server与服务客户端运行,首先进入接收IPC数据的待机状态,处理来自于Service Server或者服务客户端的请求。Context Manager的main函数大致分为三部分:

  1. binder_open函数【用来打开Binder Dirver并创建IPC数据接收Buffer】
  2. binder_become_context_manager函数【将自身的Binder结点Handler设置为0】
  3. binder_loop函数【用来不断的接收IPC数据】
0 0
原创粉丝点击