binder是Android平台的一种跨进程通信(IPC)机制,从应用层角度来说,binder是客户端和服务端进行通信的媒介。
ipc原理
ipc通信指的是两个进程之间交换数据,如图中的client进程和server进程。
Android为每个进程提供了虚拟内存空间,而每个Android进程只能运行在自己进程所拥有的虚拟内存空间。
内存空间又分为用户空间和内核空间,前者的数据不能进程间共享,但后者可以。图中的Client进程和Server进程就是利用了进程间可以共享各自内核空间的数据,来完成底层通信的工作。
Android的C/S通信机制
C/S通信指的就是Client和Server两个进程的通信,但实际通信时除了包含这两个进程,还有一个Service Manager,它用于管理各种服务。
这些服务通常是Android系统的核心功能模块,例如传感器管理、电源管理、WIFI管理、闹钟服务等等,与Android四大组件中的服务不同。
当一个Server(服务端)想要提供一种服务,首先需要在Service Manager注册该服务;
而当Client(客户端)想要使用Server中的服务时,不能直接访问,而是要从Service Manager获取该服务,才能使用Server所提供的服务,来与Server进行通信。
Binder通信模型
在引入binder机制后,客户端、服务端和Service Manager之间不能通过api直接互相访问,而是与内核空间的binder驱动通过ioctl方式来完成进程间的数据交换。
关键概念
- Binder实体对象:Binder服务的提供者,类型是BBinder,位于服务端
- Binder引用对象:Binder实体对象在客户端进程的代表,类型是BpBinder,位于客户端
- IBinder对象:Binder实体对象和引用对象的统称,也是他们的父类
- Binder代理对象:又称接口对象,为客户端的上层应用提供接口服务,类型是IInterface
Binder引用对象和代理对象都是服务端进程中的,把它们分离的好处是一个代理对象可以有多个引用对象,方便上层应用使用。
通信过程
注册服务
- server进程向binder驱动申请创建服务的binder实体
- binder驱动为这个服务创建位于内核的binder实体和binder引用
- 创建完成后,服务端通过binder驱动将binder引用发送给service manager
- service manager收到数据后,取出被创建服务的名字和引用,填入一张查找表
通过以上步骤,server进程通过binder驱动完成了在service manager的服务注册。
在注册服务的过程中,server进程是客户端,而service manager是服务端。
获取服务
- Client进程利用handle值为0的引用找到service manager
- Client进程向service manager发送xxxservice的访问申请
- service manager从请求表中获取xxxservice的名字,在查找表中找到对应的条目,取出对应的binder引用
- service manager把xxxservice的binder引用传给Client进程
使用服务
在使用服务时,Client和Server进程都是发送方和接收方。
这是因为Client在发送服务请求时,Server是接收方;当Server返回数据给Client时,Client变成了接收方。
不论发送方是谁,都会通过自身的Binder实体,把数据发送给接收方的Binder引用。binder驱动回处理发送请求,利用内核空间进程共享机制如下:
- 把发送方的数据存入写缓存(binder_write_read.write_buffer)(对于接收方这是读缓存)
- 接收方一直处于阻塞状态,当写缓存有数据,会读取数据执行命令操作
- 接收方执行操作后,会把结果返回,同样放在写缓存区(对于发送方这是读缓存)