前言:
本文是对Android进程间通信机制进行简单的框架介绍,详细介绍请看老罗的Android之旅:。Android进程间通信机制比较复杂,也比较重要,建议大家先看结合这个学习纲要仔细研究老罗的Android之旅,希望本文对大家有所帮助。
要想实现Client-Server通信必须实现以下两点:一是Server必须有确定的访问接入点或者说地址来接受Client的请求,并且Client可以通过某种途径获得Server的地址;二是制定Command-Reply协议来传输数据。例如在网络通信中Server的访问接入点就是Server主机的IP地址+端口号,传输协议为TCP协议。对Binder而言,Binder可以看成Server提供的显示某个特定服务的访问接入点(如下面说的BpXXX),Client通过这个地址向Server发送请求来使用该服务;对Client而言,Binder可以看成是通向Server的管道入口,要想和某个Server通信必须建立这个管道并且获得管道入口。
下面是重要的类和方法:
1、BpXXX:Client端(自己的应用程序)获得,然后用它和Service进行通信。
2、BnXXX:Service的父类,注册到ServiceManager,并接收Client的通信消息。
3、Server和Client获取ServiceManager远程接口的函数是defaultServiceManager,这个函数声明在frameworks/base/include/binder/IServiceManager.h文件中
4、BpServiceManager通过addService把BnXXX的子类也就是Service注册到ServiceManager即 Service_manager.c的一个list中。
一、ServiceManager的工作原理
Service_manager.c的代码位于base/cmds/servicemanager/Service_manager.c
代码如下:
intmain(intargc,char**argv)
{
structbinder_state *bs;
void*svcmgr = BINDER_SERVICE_MANAGER;
bs= binder_open(128*1024);
if(binder_become_context_manager(bs)) {
LOGE("cannotbecome context manager (%s)\n",strerror(errno));
return-1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return0;
}
原理:
1、bs =binder_open(128*1024);是打开"/dev/binder"设备
2、binder_become_context_manager(bs);告诉系统自己是ServiceManager
3、binder_loop(bs,svcmgr_handler);进入一个循环,处理BpServiceManager.addService发过来的命令,并维护一个list列表,将所有注册的Service保存在其中。
二、Service的工作原理
大致思路:首先要获得ServiceManager的代理,也就是BpServiceManager。然后通过BpServiceManager.addService把自己注册到ServiceManager中去。然后打开一个设备端口"/dev/binder",最后进入循环等待Client的请求。
代码:(MediaService是一个程序,里面注册了4个Service到ServiceManager,代码目录:
framework\base\Media\MediaServer\Main_mediaserver.cpp)
intmain(intargc,char**argv)
{
sp<ProcessState>proc(ProcessState::self());
sp<IServiceManager> sm =defaultServiceManager();
LOGI("ServiceManager:%p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
原理:
1、sp<ProcessState>proc(ProcessState::self());打开/dev/binder设备,这样的话就相当于和内核binder机制有了交互的通道.
2、sp<IServiceManager>sm =defaultServiceManager();获得BpServiceManager对象,该对象引用了一个BpBinder对象,BpBinder才是真正和ServiceManager进行通信的接口。
3、MediaPlayerService::instantiate();调用BpServiceManager.addService把Service注册到 ServiceManager,实际上是调用了BpBinder->transact进行注册。
4、ProcessState::self()->startThreadPool();和IPCThreadState::self()->joinThreadPool();
Service进入循环等待Client的请求。
三、Client的工作原理
原理:
1、获得BpServiceManager对象,例如sp<IServiceManager>sm = defaultServiceManager();
2、通过BpServiceManager->gerService获得服务对象的代理,如:BpMediaPlayerService。例如:binder= sm->getService(String16("media.player"));
3、调用BpMediaPlayerService的方法即可与BnMediaPlayerService(MediaPlayerService的父类)通信.
四、使用Java语言通过Binder机制来进行进程间通信
在应用程序中,我们都是把Server实现为Service的形式,并且通过IServiceManager.addService接口来把这个Service添加到ServiceManager,Client也是通过IServiceManager.getService接口来获得Service接口,接着就可以使用这个Service提供的功能了,这个与运行时库的Binder接口是一致的。
1、获取ServiceManager的Java远程接口
我们要获取的ServiceManager的Java远程接口是一个ServiceManagerProxy对象,它实现了接口IServiceManager,IServiceManager提供了getService和addService两个成员函数来管理系统中的Service。
ServiceManager类有一个静态成员函数getIServiceManager,它的作用就是用来获取ServiceManager的Java远程接口ServiceManagerProxy。从ServiceManagerProxy类的构造函数可以看出,它需要一个BinderProxy对象的IBinder接口来作为参数。因此,要获取ServiceManager的Java远程接口ServiceManagerProxy,首先要有一个BinderProxy对象,从而使这个ServiceManagerProxy对象在JNI层有一个句柄值为0的BpBinder对象与之通过gBinderProxyOffsets关联起来。
2、Service的启动过程
在frameworks/base/services/java/com/android/server/SystemServer.java文件中,定义了SystemServer类。SystemServer对象是在系统启动的时候创建的,它被创建的时候会启动一个线程ServerThread来创建要启动的Service,并且把它添加到ServiceManager中去。
3、Client获得Service的远程接口
通过ServiceManager.getService获得Service的远程接口。在ServiceManager.getService中:returngetIServiceManager().getService(name)先获得ServiceManager的代理ServiceManagerProxy,然后调用ServiceManagerProxy.getService获得Service的远程接口。