Understanding Android Source: Binder Library

起源

Android Binder的前身是OpenBinder,已经于2014年10月合并入Linux主线,得到Linux阵营的认可。
其可以理解为一种面向对象的远程调用,其优势有:

  • 无需关心线程同步;
  • 无需关心内存分配;
Android Binder Library

Android Binder Library

Binder Library

Binder进程间通信机制里,有四个大类/接口发挥着关键作用:

  • IInterface
  • IBinder
  • ProcessState
  • IPCThreadState

IInterface

Service组件和Client组件分别使用模板类BnInterfaceBpInterface来描述,二者都继承自IInterface,且都是模板类,其模板参数INTERFACE是一个进程自定义的Service组件接口。

BnInterface继承自BBinder,并借助了后者抽象的进程间通信接口。BpInterface继承自BpRefBase,并同样借助了其抽象的进程间通信接口。

理解IInterface相关类,有两个宏非常重要:DECLARE_META_INTERFACEIMPLEMENT_META_INTERFACE。通过前者,每个接口将会有一个static变量 descriptor,还有一个方法asInterface

asInteface方法是把IBinder对象转换成IInterface对象,分两种情况:

  • 在Client进程中调用,则会新创建一个BpBinder,其关联了binder_ref
  • 在Service进程中调用,则会返回参数的指针,因为在Service进程中可以直接调用服务类。

IBinder

IBinder定义了进程间通信接口,transact是其重要的成员方法。

BBinder是服务提供者,Binder服务类必须继承自它。成员函数onTransact是由其子类来实现的,负责分发与业务相关的进程间通信请求。

BpBinder是Binder服务在客户端的代表/代理。其成员变量mHandle是标示一个Client组件的句柄值,而这个值也正是Binder驱动程序中binder_refdesc

由此,当Client组件通过BpBindermHandle,经由Binder驱动程序找到对应的binder_ref,并由其成员node找到对应的binder_node,最后找到要访问的Service组件。

ProcessState

每个进程只有一个ProcessState对象实例,负责管理客户进程中所有的BpBinder,负责创建和释放。Binder线程池中每个线程都是通过它来和Binder驱动程序建立连接。

ProcessState在其构造函数中,完成了两个重要事情:

  1. 调用open_binder打开binder设备;
  2. 调用mmap在驱动中分配内存空间,用于Binder驱动中接收传递给本进程的Binder数据。

设备文件/dev/binder映射到进程的地址空间后,得到的内核缓冲区的用户地址就保存在其成员变量mVMStart中。

IPCThreadState

无论是BnInterface,还是BpInterface,它们都是要通过IPCThreadState类和Binder驱动打交道,每个Binder线程都会关联一个该对象,发送和接收Binder数据,处理和驱动之间的消息。其四个成员函数非常重要:

  • waitForResponse
  • joinThreadPool
  • talkWithDriver
  • executeCommand

IPCThreadState和Binder驱动之间通过ioctl来传递数据,其中三个命令非常关键:

BINDER_WRITE_READ
向驱动读取和写入数据,既可以单独读或写,也可以同时读和写,通过命令中的数据中有无读写数据来控制。关联的结构体是binder_write_readbinder_transcation_data
BINDER_SET_CONTEXT_MGR

将本进程设置为Binder管理进程,只有ServiceManager进程才会使用这个命令。
BINDER_THREAD_EXIT
通知驱动当前线程要退出,以便驱动清理和该线程有关系的数据。

Leave a comment

Your comment