Android binder学习一:主要概念

要看得懂android代码,首先要了解binder机制。binder机制也是android里面比较难以理解的一块,这里记录一下binder的重要概念以及实现,作为备忘。部分内容来源于网上,如有侵权,请及时告知。

1.binder通信机制概述

binder通信是一种client-server的通信结构,1.从表面上来看,是client通过获得一个server的代理接口,对server进行直接调用;2.实际上,代理接口中定义的方法与server中定义的方法是一一对应的;3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象;4.代理接口将该Parcel发送给内核中的binder driver.5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。

2.为什么使用binder通信

linux中有管道,system V IPC,socket等进程间通信机制,那么为什么在android中使用了一个全新的binder通信机制呢?

一、可靠性。在移动设备上,通常采用基于Client-Server的通信方式来实现互联网与设备间的内部通信。目前linux支持IPC包括传统的管道,System V IPC,即消息队列/共享内存/信号量,以及socket中只有socket支持Client-Server的通信方式。Android系统为开发者提供了丰富进程间通信的功能接口,媒体播放,传感器,无线传输。这些功能都由不同的server来管理。开发都只关心将自己应用程序的client与server的通信建立起来便可以使用这个服务。毫无疑问,如若在底层架设一套协议来实现Client-Server通信,增加了系统的复杂性。在资源有限的手机 上来实现这种复杂的环境,可靠性难以保证。

二、传输性能。socket主要用于跨网络的进程间通信和本机上进程间的通信,但传输效率低,开销大。消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的一块缓存区中,然后从内核缓存区拷贝到接收方缓存区,其过程至少有两次拷贝。虽然共享内存无需拷贝,但控制复杂。比较各种IPC方式的数据拷贝次数。共享内存:0次。Binder:1次。Socket/管道/消息队列:2次。

IPC数据拷贝次数

共享内存0

Binder1

Socket/管道/消息队列2

三、安全性。Android是一个开放式的平台,所以确保应用程序安全是很重要的。Android对每一个安装应用都分配了UID/PID,其中进程的UID是可用来鉴别进程身份。传统的只能由用户在数据包里填写UID/PID,这样不可靠,容易被恶意程序利用。而我们要求由内核来添加可靠的UID。

基于以上原因,Android需要建立一套新的IPC机制来满足系统对通信方式,传输性能和安全性的要求,这就是Binder。Binder基于Client-Server通信模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性高。

3.service manager

顾名思义,service manager就是android下面管理service的一个进程,它本身也是一个service,这里的service和init.rc里面的service有一些差别,init.rc中的service都是一个进程,而这里的service可能不是一个单独的进程。每一个service在使用之前都必须向SM注册,每一个client要使用service前都应该先向SM查询是否存在这个service,如果存在,则给client返回这个service的handle。下面是sm中main函数的关键代码:

int main(int argc, char **argv){struct binder_state *bs;bs = binder_open(128*1024);if (!bs) {ALOGE("failed to open binder driver\n");return -1;}if (binder_become_context_manager(bs)) {ALOGE("cannot become context manager (%s)\n", strerror(errno));return -1;}……//svcmgr_handle的值为0svcmgr_handle = BINDER_SERVICE_MANAGER;binder_loop(bs, svcmgr_handler);return 0;}

在SM中主要做了如下工作:

下面一个图片可以简单说明SM与binder driver之间的关系:

由上可知,service在使用前会先作为client向SM注册;应用若要使用某一个服务,需要先向SM获取该服务的handle,然后通过handle来调用该服务提供的方法。

4.ProcessState

ProcessState是以单例模式设计的。每个进程在使用binder机制通信时,均需要维护一个ProcessState实例来描述当前进程在binder通信时的binder状态。ProcessState有如下2个主要功能:1.创建一个thread,该线程负责与内核中的binder模块进行通信,称该线程为Pool thread;2.为指定的handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。

4.1 Pool thread

在Binder IPC中,所有进程均会启动一个thread来负责与BD(binder driver)来直接通信,也就是不停的读写BD,这个线程的实现主体是一个IPCThreadState对象,下面会介绍这个类型。

下面是 Pool thread的启动方式:ProcessState::self()->startThreadPool();

4.2 BpBinder获取

BpBinder主要功能是负责client向BD发送调用请求的数据。它是client端binder通信的核心对象,通过调用transact函数向BD发送调用请求的数据,它的构造函数如下:

BpBinder(int32_t handle);

通过BpBinder的构造函数发现,BpBinder会将当前通信中server的handle记录下来,当有数据发送时,会通知BD数据的发送目标ProcessState通过如下方式来获取BpBinder对象:

ProcessState::self()->getContextObject(handle);

在这个过程中,ProcessState会维护一个BpBinder的vector mHandleToObject,每当ProcessState创建一个BpBinder的实例时,回去查询mHandleToObject,如果对应的handle已经有binder指针,那么不再创建,否则创建binder并插入到mHandleToObject中。ProcessState创建的BpBinder实例,一般情况下会作为参数构建一个client端的代理接口,这个代理接口的形式为BpINTERFACE,例如在与SM通信时,client会创建一个代理接口BpServiceManager。

5.IPCThreadState但一定要背上几本书,在花海里,草丛旁悠然品味,

Android binder学习一:主要概念

相关文章:

你感兴趣的文章:

标签云: