Android进程间通信机制

前言:

本文是对Android进程间通信机制进行简单的框架介绍,详细介绍请看老罗的Android之旅:http://blog.csdn.net/luoshengyang/article/details/6618363Android进程间通信机制比较复杂,也比较重要,建议大家先看结合这个学习纲要仔细研究老罗的Android之旅,希望本文对大家有所帮助。

要想实现Client-Server通信必须实现以下两点:一是Server必须有确定的访问接入点或者说地址来接受Client的请求,并且Client可以通过某种途径获得Server的地址;二是制定Command-Reply协议来传输数据。例如在网络通信中Server的访问接入点就是Server主机的IP地址+端口号,传输协议为TCP协议。对Binder而言,Binder可以看成Server提供的显示某个特定服务的访问接入点(如下面说的BpXXX)Client通过这个地址向Server发送请求来使用该服务;对Client而言,Binder可以看成是通向Server的管道入口,要想和某个Server通信必须建立这个管道并且获得管道入口。

下面是重要的类和方法:

1BpXXX:Client(自己的应用程序)获得,然后用它和Service进行通信。

2BnXXX:Service的父类,注册到ServiceManager,并接收Client的通信消息。

3ServerClient获取ServiceManager远程接口的函数是defaultServiceManager,这个函数声明在frameworks/base/include/binder/IServiceManager.h文件中

4BpServiceManager通过addServiceBnXXX的子类也就是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;

}

原理:

1bs =binder_open(128*1024);是打开"/dev/binder"设备

2binder_become_context_manager(bs);告诉系统自己是ServiceManager

3binder_loop(bs,svcmgr_handler);进入一个循环,处理BpServiceManager.addService发过来的命令,并维护一个list列表,将所有注册的Service保存在其中。


二、Service的工作原理

大致思路:首先要获得ServiceManager的代理,也就是BpServiceManager。然后通过BpServiceManager.addService把自己注册到ServiceManager中去。然后打开一个设备端口"/dev/binder",最后进入循环等待Client的请求。

代码:MediaService是一个程序,里面注册了4ServiceServiceManager,代码目录: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();

}

原理:

1sp<ProcessState>proc(ProcessState::self());打开/dev/binder设备,这样的话就相当于和内核binder机制有了交互的通道.

2sp<IServiceManager>sm =defaultServiceManager();获得BpServiceManager对象,该对象引用了一个BpBinder对象,BpBinder才是真正和ServiceManager进行通信的接口。

3MediaPlayerService::instantiate();调用BpServiceManager.addServiceService注册到 ServiceManager,实际上是调用了BpBinder->transact进行注册。

4ProcessState::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添加到ServiceManagerClient也是通过IServiceManager.getService接口来获得Service接口,接着就可以使用这个Service提供的功能了,这个与运行时库的Binder接口是一致的。

1、获取ServiceManagerJava远程接口

我们要获取的ServiceManagerJava远程接口是一个ServiceManagerProxy对象,它实现了接口IServiceManagerIServiceManager提供了getServiceaddService两个成员函数来管理系统中的Service

ServiceManager类有一个静态成员函数getIServiceManager,它的作用就是用来获取ServiceManagerJava远程接口ServiceManagerProxy。从ServiceManagerProxy类的构造函数可以看出,它需要一个BinderProxy对象的IBinder接口来作为参数。因此,要获取ServiceManagerJava远程接口ServiceManagerProxy,首先要有一个BinderProxy对象,从而使这个ServiceManagerProxy对象在JNI层有一个句柄值为0BpBinder对象与之通过gBinderProxyOffsets关联起来。


2Service的启动过程

frameworks/base/services/java/com/android/server/SystemServer.java文件中,定义了SystemServer类。SystemServer对象是在系统启动的时候创建的,它被创建的时候会启动一个线程ServerThread来创建要启动的Service,并且把它添加到ServiceManager中去。


3Client获得Service的远程接口

通过ServiceManager.getService获得Service的远程接口。在ServiceManager.getService中:returngetIServiceManager().getService(name)先获得ServiceManager的代理ServiceManagerProxy,然后调用ServiceManagerProxy.getService获得Service的远程接口。

你可能感兴趣的:(进程通信,Binder机制,Android进程间通信机制)