[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. Service Manager
Service Manager是一个linux级的进程,顾名思义,就是Service的管理器。这里的Service是什么概念呢?这里的Service的概念和init过程中init.rc中的Service是不同的,init.rc中的Service都是Linux进程,但是这里的Service它并不一定是一个进程,也就是说可能多个Service属于同一个Linux进程。本文中,如不加特殊说明均指Android native端的Service。
任何Service在被使用之前,均要向SM(Service Manager)注册,同时客户端需要访问某个Service时,应该首先向SM查询是否存在该服务,如果SM存在这个Service,那么会将该Service的handle返回给Client,handle是每个Service的唯一标识符。
/* Android4.3-Code/frameworks/native/cmds/servicemanager/service_manager.c */ int main(int argh, char **argv) { struct binder_state *bs; void *svcmgr = BINDER_SERVICE_MANAGER;
/* Android4.3-Code/frameworks/native/cmds/servicemanager/binder.h :
* #define BINDER_SERVICE_MANAGER ((VOID *)0)
*/
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
这个进程的主要工作如下:
1. 初始化Binder,打开设备/dev/binder设备,在内存中为binder映射128K字节空间(Binder本质为ShareMemory);
2. 指定SM对应的代理binder的handle为0,当Client尝试与SM通信时,需要创建一个handle为0的代理Binder,这里的代理Binder其实就是第一节中描述的那个代理接口;
3. 通知Binder Driver(BD)使SM成为BD的context manager;
4. 维护一个死循环,在这个死循环中,不停地去读取内核中BD,查看是否有可读的内容;即是否具有对Service的操作请求,如果有,则调用svcmgr_handler回调来处理请求的操作;
5. SM维护了一个svclist列表来存储service的信息。
这里需要声明一下,当Service在向SM注册时,该Service就是一个Client,而SM则作为Server。当某个进程需要与该Service通信时,此时这个进程为Client,Service作为Server。因此Service不一定为Server,有时它也是作为Client存在的。
应用和Service之间的通信会涉及到2次Binder通信:
1. 应用向SM查询Service是否存在,如果存在则获得该Service的代理Binder,此为一次Binder通信;
2. 应用通过代理Binder调用Service的方法,此为第二次Binder通信。
3. ProcessState
ProcessState是以单例模式设计的。每个进程在使用Binder机制通信时,均需要维护一个ProcessState实例来描述当前进程在Binder通信时的状态。
ProcessState有如下两个功能:
1. 创建一个Thread,该线程负责与内核中的Binder模块进行通信,该线程称为Pool Thread;
2. 为指定的Handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。
3.1 Pool Thread
在Binder IPC中,所有的进程均会启动一个Thread来负责与BD来直接通信,也就是不停的读写BD,这个线程的实现主体是一个IPCThreadState对象,下面会介绍。
/* * Pool Thread 启动方式 */ ProcessState::self()->startThreadPool();
3.2 BpBinder获取
BpBinder主要功能是负责Client向BD发送调用请求的数据。它是Client端Binder通信的核心对象,通过调用transact函数向BD发送调用请求的数据。
BpBinder会将当前通信中的server的handle记录下来,当有数据发送时,会通知BD数据发送的目标。
ProcessState通过如下方式来获取BpBinder对象:
/* * ProcessState获取BpBinder的方式 */ ProcessState::self()->getContextObject(handle);
在这个过程中,ProcessState会维护一个BpBinder的Vector mHandleToObject,每当ProcessState创建一个BpBinder的实例时,会去查询mHandleToObject,如果对应的handle已经有Binder指针,那么不再创建,否则创建Binder并插入到mHandleToObject中。
ProcessState创建的BpBinder实例,一般情况下会作为参数构建一个Client端的代理接口,这个代理接口的形式为BpINTERFACE,例如在与SM通信时,Client会创建一个代理接口BpServiceManager。
4. IPCThreadState
IPCThreadState是以单例模式设计的。由于每个进程只维护了一个ProcessState实例,同时ProcessState只启动一个Pool Thread,也就是说每一个进程只会启动一个Pool Thread,因此每个进程只需要一个IPCThreadState即可。
Pool Thread的实际内容为:
/* * PoolThread */ virtual bool threadLoop() { IPCThreadState::self()->joinThreadPool(mIsMain); return false; }
ProcessState有两个Parcel成员,mIn和mOut,Pool Thread会不停的查询BD中是否有数据可读,如果有将其读出并保存到mIn中,同时不停的检查mOut是否有数据需要向BD发送,如果有,将其内容写到BD中。总之:从BD中读出的数据保存到mIn,待写入到BD中的数据保存到mOut中。
IPCThreadState有两个重要的函数,talkWithDriver函数负责从BD读写数据,executeCommand函数负责解析并执行mIn中的数据。


浙公网安备 33010602011771号