Understanding Android Source: Binder Library
起源
Android Binder的前身是OpenBinder,已经于2014年10月合并入Linux主线,得到Linux阵营的认可。
其可以理解为一种面向对象的远程调用,其优势有:
- 无需关心线程同步;
- 无需关心内存分配;
Binder Library
Binder进程间通信机制里,有四个大类/接口发挥着关键作用:
IInterface
IBinder
ProcessState
IPCThreadState
IInterface
Service组件和Client组件分别使用模板类BnInterface
和BpInterface
来描述,二者都继承自IInterface
,且都是模板类,其模板参数INTERFACE
是一个进程自定义的Service组件接口。
BnInterface
继承自BBinder
,并借助了后者抽象的进程间通信接口。BpInterface
继承自BpRefBase
,并同样借助了其抽象的进程间通信接口。
理解IInterface
相关类,有两个宏非常重要:DECLARE_META_INTERFACE
、IMPLEMENT_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_ref
的desc
。
由此,当Client组件通过BpBinder
的mHandle
,经由Binder驱动程序找到对应的binder_ref
,并由其成员node
找到对应的binder_node
,最后找到要访问的Service组件。
ProcessState
每个进程只有一个ProcessState
对象实例,负责管理客户进程中所有的BpBinder,负责创建和释放。Binder线程池中每个线程都是通过它来和Binder驱动程序建立连接。
ProcessState
在其构造函数中,完成了两个重要事情:
- 调用
open_binder
打开binder设备; - 调用
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_read
和binder_transcation_data
BINDER_SET_CONTEXT_MGR
- 将本进程设置为Binder管理进程,只有ServiceManager进程才会使用这个命令。
BINDER_THREAD_EXIT
- 通知驱动当前线程要退出,以便驱动清理和该线程有关系的数据。