[TOC]

概述

Binder是Android特有的一种进程间通信(IPC)方式。Android Binder的前身是OpenBinder,最早由Dianne Hackborn开发并用于PalmOS上,后来Dianne Hackborn加入Google,在OpenBinder的基础上开发了Android Binder。

Binder和传统的IPC机制相比,融合了远程过程调用(RPC)的概念,而且这种远程调用不是传统的面向过程的远程调用,而是一种面向对象的远程调用。

从Unix发展而来的IPC机制,只能提供比较原始的进程间通信手段,通信的双方必须处理线程同步、内存管理等复杂问题,不但工作量大,而且很容易出错。除了Socket、匿名管道(Pipe)以外,传统的IPC,如命名管道(FIFO)、信号量(Semaphore)、消息队列等已经从Android中去掉了。和其他IPC相比较,Socket是一种比较成熟的通信手段,同步控制也很容易实现。Socket用于网络通信非常合适,但是用于进程间通信,效率就不太高了。

Andoid在架构上一直希望模糊进程的概念,取而代之以组件的概念。应用不需要关心组件存放的位置、组件运行在哪个进程中、组件的生命周期等问题。随时随地,只要拥有Binder对象,就能使用组件的功能。Binder就像一张网,将整个系统的组件,跨越进程和线程,组织在了一起。

Binder很强大,也很复杂。但是无论调用Binder服务,还是开发一个Binder服务都是一件很轻松的事情,不需要考虑线程同步、内存分配等问题,和开发一个普通的类没有太大的区别,所有这些麻烦问题都在Binder框架中解决了。

正因为如此,Android系统的服务都是利用Binder构建的。Android系统中的服务有几十种之多,这是任何一个其他嵌入式平台都不具备的。

Binder是整个系统运行的中枢,因此,Android在提高Binder的效率方面也下足了功夫。Android在进程间传递数据使用的是共享内存的方式,这样数据只需要复制一次就能从一个进程到达另一个进程(一般的IPC都需要两步,从用户进程复制到内核,再从内核复制到服务进程),这样数据传输的效率就大大提高了。

在安全性方面Android也做了考虑,Binder调用时会传递调用进程的euid到服务端,因此,服务端可以通过检查调用进程的权限来决定是否允许其使用所调用的服务。

Binder对象定义

Binder涉及的对象比较多,很容易混淆,为了行文方便,这里对Binder对象做出了定义,这些并非官方的定义,只是本文使用的代称。

(1)Binder实体对象:Binder实体对象就是Binder服务的提供者。一个提供Binder服务的类必须继承BBinder类,因此,有时为了强调对象的类型,也用“BBinder对象”来代替“Binder实体对象”。

(2)Binder引用对象:Binder引用对象是Binder实体对象在客户进程的代表,每个引用对象的类型都是BpBinder类,同样可以用名称“BpBinder对象”来代替“Binder引用对象”。

(3)Binder代理对象:代理对象也称为接口对象,它主要是为客户端的上层应用提供接口服务,从IInterface类派生。它实现了Binder服务的函数接口,当然只是一个转调的空壳。通过代理对象,应用能像使用本地对象一样使用远端的实体对象提供的服务。

(4)IBinder对象:BBinder和BpBinder类都是从IBinder类中继承而来。在很多场合,不需要刻意地去区分实体对象和引用对象,这时可以使用“IBinder对象”来统一称呼它们。

image-20230109110111802

应用完全可以抛开接口对象直接使用Binder的引用对象,但是这样开发的程序兼客性不好。也正是在客户端将引用对象和代理对象分离,Android才能用一套架构来同时为Java和native层提供Binder服务。隔离后,Binder底层不需要关心上层的实现细节,只需要和Binder实体对象和引用对象进行交互。

Binder的架构

Binder通信的参与者由4部分组成。

(1)Binder驱动:Binder的核心,实现各种Binder的底层操作。

(2)ServiceManager:提供Binder的名称到引用对象的转换服务。

(3)服务端:Binder服务的提供者。

(4)客户端:Binder服务的使用者。

这4部分的关系如图4.2所示。

img