Binder 学习http://blog.csdn.net/ylyuanlu/article/details/6629332
Binder 的应用模型
一个IPC通讯我们可以简单的理解成客户端-服务器模式,客户端请求服务,服务端接收到客户端请求后处理相应的请求,或可能带回结果返回给客户端。Binder机制在Android系统的进程间通讯模型总结如下:
1)客户端通过某种方式得到服务器端的代理对象。从客户端角度看来代理对象和他的本地对象没有什么差别。他可以像其他本地对象一样调用其方法,访问其变量。
2)客户端通过调用代理对象的方法向服务器端发送请求信息。
3)代理对象通过binder设备节点(/dev/binder),把用户请求信息发送到Linux内核空间(实际上市内存共享),由binder驱动获取并发送到服务进程。
4)服务器进程处理用户请求,并通过Linux内核的binder驱动返回处理结果给客户端的代理对象。
5)客户端收到服务端的返回结果。
整个过程大致如上所述,可以想象一下binder机制的引入,给进程间的通讯带来什么好处?没错就是线程迁移,就像是一个线程带着参数,进入另一个进程执行,然后带着结果返回,和调用自己的函数一样的效果。
Binder机制的组成
1)binder驱动:binder是内核中的一个字符驱动设备位于/dev/binder。这个设备是Android系统IPC的核心部分,客户端的代理服务来通过它想服务器(server)发送请求,服务器也是通过它把处理结果返回给客户端的服务代理。这部分内容,在Android中通过一个IPCThreadState对象封装了对Binder驱动的操作。
2)Service Manager:这个东西主要用来负责管理服务。Android中提供的系统服务都要通过Service Manager注册自己,将自己添加进服务管理链表中,为客户提供服务服务。而客户端如果要和特定的系统服务端通讯,就要向Service Manager来查询和获得所需要服务。可以看出Service Manager是系统服务对象的管理中心。
3)服务(Server):需要强调的是这里服务是指的是System Server,而不是SDK Server,向客户端提供服务。
4)客户端:一般是指Android系统上面的应用程序。它可以请求Server中的服务。
5)代理对象:是指在客户端应用程序中获取生成的Server代理(proxy)类对象。从应用程序角度看代理对象和本地对象没有差别,都可以调用其方法,方法都是同步的,并且返回相应的结果。
Binder机制的实现使用c c++实现的,但在Android的应用程序中,也会有java部分的内容。
Binder 之Service Manager
Service Manager在Android binder机制中的地位是相当的重要,所有的Server(System Server)都要向他注册,应用程序需要向其查询相应的服务。
service_manager.c是Service Manager的入口
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);//打开binder设备,然后将该文件映射到内存中,并返回这块内存的首地址这样我们就可以像操作内存一样,来操作这个文件了。
if (binder_become_context_manager(bs)) {//这个函数就是调用binder的ioctl设置成服务大管家。
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);//Service Manager的核心-循环体,调用一个回调函数,处理不同的请求
return 0;
}
Binder 之 服务代理对象
服务代理对象的应用模型:
1)首先客户端向Service Manager查找相应的Service
2)Android系统的binder机制将会为客户端进程创建一个Service代理
3)客户端视角只有Service代理,他所有对Service的请求都发往Service代理,然后由Service代理把用户请求转发给Service本身
4)Service处理完成后,吧结果返回给Service代理,Service代理负责把结果返回给客户端
在Android系统中的任何进程,要想使用binder机制,必须要创建一个ProcessState对象和IPCThreadState对象。
我们知道一个客户端进程可能有多个Service的服务,这样就会创建多个Service代理(BPBinder对象),那么这个进程就需要一个东东来管理这些服务代理。ProcessState就是这个东东,它的作用就是维护当前进程中的所有Service代理。
defaultServiceManager生成一个IserviceManager对象sm,即Service Manager的服务代理,进程就是通过这个代理对象sm和Service Manager通讯的,提供给本进程的其他服务器端或客户端访问Service Manager的接口。
Binder 的服务代理对象步骤:
1)创建ProcessState对象,用来管理本进程中获取的服务代理对象(根据客户端传的值),每个进程智能创建一个该对象。
2)获取了Service Manager的服务代理对象,可以通过这个对象和服务管家通讯了
3)实例化一些服务,并通过Service Manager代理对象向服务管家添加这些服务
4)服务端准备好了,就进入循环状态,接收来自客户端的请求
IPCThreadState对象的作用:
1)维护当前进程中所有对/dev/binder的读写,就是说当前进程通过binder机制进行跨进程条用都是通过IPCThreadState对象完成的
2)IPCThreadState也可以理解成/dev/binder设备的封装,用户可以不直接通过ioctl来操作binder设备
3)这个对象里肯定有循环的从binder设备中拿信息,然后处理
4)如果是客户端进程,则通过服务代理BpBinder对象,调用transact函数,该函数作用就是把客户端的请求写入binder设备另一端的Service进程
5)作为Service进程,当他完成初始化工作之后,他们需要进入循环状态等待客户端的请求,Service进程调用他的IPCThreadState对象的joinThreadPool方法,开始轮询binder设备,等待客户端请求的到来
Binder 客户端
整个服务代理的获取过程也是binder机制的核心内容,它涉及了客户请求,请求的传递和处理,服务代理的生成和转换(封装)过程。当客户端获取到对应服务的代理后,就可以通过这个服务代理和服务通讯了。
Binder机制中的java层
我们知道Android中的应用程序基本上都是java开发,对Android的框架了解的朋友都知道,java的本地实现都是通过jni层的接口来调用C/C++代码的,这里也不例外。在Android的binder机制中,java层面的binder机制的应用,你可以简单看作是底层binder机制的封装。
1)ServiceManager类型和对象
我们都知道作为客户端要想获得服务代理,首相要创建ServiceManager代理对象,查询Service,然后创建并返回服务代理对象,再通过代理对象和Service通讯。
查看源码ServiceManager就是IServiceManager对象的一个代理,他就是客户端代理对象的一个封装,因为创建和访问这个代理对象都是通过ServiceManager的getIServiceManager方法,我们创建ServiceManager服务对象,是通过jni调用native代码,就是java的本地接口,来和底层的C/C++实现挂钩。创建一个服务代理对象BpBinder,在native层,BpBinder继承IBinder接口,把native层的IBinder对象封装成java层的IBinder对象。之后根据描述符,查找BpBinder对应的本地服务代理对象并转换为IserviceManager类型
Binder之编程模型
1)在service_manager.c的结构数组allowed中添加新的服务名称
2)定义一个继承IInterface接口的ImyService.h
Class ImyService:public IInterface
{
Public:
DECLARE_META_INTERFACE(MyService);//重要的地方就是,这个宏定义和下个宏
....虚函数
}
3)跟着在ImyService.h中定义本地实现类BnMyService,需要继承BnInterface,间接继承了IMyService和BBinder
Class BnMyService:public BnInterface<IMyService>
{
virtual status_t onTransact();
}
4)在IMyService.cpp中,定义接口代理类BpMyService,需要继承BpInterface
Class BpMyService:public BpInterface<IMyService>
{
Public:
BpMyservice(const sp<IBinder>& impl)
:BpInterface<IMyService>(impl){}//这里的impl就是个BpBinder对象,和binder扯上关系
....h文件中定义的虚函数实现
}
5)在IMyService.cpp加入宏定义IMPLEMENT_META_INTERFACE(MyService,”***”)//这个宏和上个宏,new一个BpMyService类,并传个BpBinder进去。
6)在IMyService.cpp中实现BnMyService类的onTrasact()接收BpMyService的onTrasact通过IPCThreadState发过来的数据,
7)创建真正的本地接口实现类MyService类头文件,继承BnMyService,定义功能函数和初始化函数instantiate()
8)在本地实现类MyService.cpp的instatiate()中把这个服务注册到ServiceManager服务管家
9)在服务的进程入口函数里调用服务的instantiate;这之后服务端的binder就搭建完成了
10)客户端获取服务代理对象
客户端进程想要和服务端通讯,首先需要获取ServiceManager的代理对象,然后查找服务,返回该服务代理对象的引用,此代理对象中包含一个指向查找的服务的handle句柄
11)客户端调用服务端函数
客户端进程调用MyService的接口函数,调用会传递给包含了服务对象handler的代理对象的BpBinder,写入binder内核驱动,binder驱动知道数据传递到的对象,于是将数据传递给该进程;服务端进程从binder驱动中读取数据,然后处理远程调用,然后发送reply数据给binder驱动,binder驱动将reply传递给客户端进程,客户端进程从binder驱动中读取数据并最终获取到reply,从而完成进程通信。
来源:oschina
链接:https://my.oschina.net/u/2009657/blog/312895