一只刚刚上路的猿 2010-10-09
Android IPC 通讯机制源码分析----Albertchen
Binder通信简介:
Linux系统中进程间通信的方式有:socket,namedpipe,messagequeque,signal,sharememory。Java系统中的进程间通信方式有socket,namedpipe等,android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信,但我查看android的源码,在同一终端上的应用软件的通信几乎看不到这些IPC通信方式,取而代之的是Binder通信。Google为什么要采用这种方式呢,这取决于Binder通信方式的高效率。Binder通信是通过linux的binderdriver来实现的,Binder通信操作类似线程迁移(threadmigration),两个进程间IPC看起来就象是一个进程进入另一个进程执行代码然后带着执行的结果返回。Binder的用户空间为每一个进程维护着一个可用的线程池,线程池用于处理到来的IPC以及执行进程本地消息,Binder通信是同步而不是异步。
Android中的Binder通信是基于Service与Client的,所有需要IBinder通信的进程都必须创建一个IBinder接口,系统中有一个进程管理所有的systemservice,Android不允许用户添加非授权的Systemservice,当然现在源码开发了,我们可以修改一些代码来实现添加底层systemService的目的。对用户程序来说,我们也要创建server,或者Service用于进程间通信,这里有一个ActivityManagerService管理JAVA应用层所有的service创建与连接(connect),disconnect,所有的Activity也是通过这个service来启动,加载的。ActivityManagerService也是加载在SystemsServcie中的。
Android虚拟机启动之前系统会先启动serviceManager进程,serviceManager打开binder驱动,并通知binderkernel驱动程序这个进程将作为SystemServiceManager,然后该进程将进入一个循环,等待处理来自其他进程的数据。用户创建一个Systemservice后,通过defaultServiceManager得到一个远程ServiceManager的接口,通过这个接口我们可以调用addService函数将Systemservice添加到ServiceManager进程中,然后client可以通过getService获取到需要连接的目的Service的IBinder对象,这个IBinder是Service的BBinder在binderkernel的一个参考,所以serviceIBinder在binderkernel中不会存在相同的两个IBinder对象,每一个Client进程同样需要打开Binder驱动程序。对用户程序而言,我们获得这个对象就可以通过binderkernel访问service对象中的方法。Client与Service在不同的进程中,通过这种方式实现了类似线程间的迁移的通信方式,对用户程序而言当调用Service返回的IBinder接口后,访问Service中的方法就如同调用自己的函数。
下图为client与Service建立连接的示意图首先从ServiceManager注册过程来逐步分析上述过程是如何实现的。
ServiceMananger进程注册过程源码分析:
ServiceManagerProcess(Service_manager.c):
Service_manager为其他进程的Service提供管理,这个服务程序必须在AndroidRuntime起来之前运行,否则AndroidJAVAVmActivityManagerService无法注册。
intmain(intargc,char**argv)
{
structbinder_state*bs;
void *svcmgr = BINDER_SERVICE_MANAGER;bs = binder_open(128*1024); //打开/dev/binder 驱动
if (binder_become_context_manager(bs)) {//注册为service manager in binder kernel
LOGE("cannotbecomecontextmanager(%s)\n",strerror(errno));
return-1;
}
svcmgr_handle=svcmgr;
binder_loop(bs,svcmgr_handler);
return0;
}
首先打开binder的驱动程序然后通过binder_become_context_manager函数调用ioctl告诉BinderKernel驱动程序这是一个服务管理进程,然后调用binder_loop等待来自其他进程的数据。BINDER_SERVICE_MANAGER是服务管理进程的句柄,它的定义是:
/*theonemagicobject*/
#defineBINDER_SERVICE_MANAGER((void*)0)
如果客户端进程获取Service时所使用的句柄与此不符,Service Manager将不接受Client的请求。客户端如何设置这个句柄在下面会介绍。CameraSerivce服务的注册(Main_mediaservice.c)
intmain(intargc,char**argv)
{
sp<ProcessState>proc(ProcessState::self());
sp<IServiceManager>sm=defaultServiceManager();
LOGI("ServiceManager:%p",sm.get());
AudioFlinger::instantiate();//Audio服务
MediaPlayerService::instantiate();//mediaPlayer服务
CameraService::instantiate();//Camera服务
ProcessState::self()->startThreadPool();//为进程开启缓冲池
IPCThreadState::self()->joinThreadPool();//将进程加入到缓冲池
}CameraService.cpp
voidCameraService::instantiate(){
defaultServiceManager()->addService(
String16("media.camera"),newCameraService());
}
创建CameraService服务对象并添加到ServiceManager进程中。client获取remoteIServiceManagerIBinder接口:
sp<IServiceManager>defaultServiceManager()
{
if(gDefaultServiceManager!=NULL)returngDefaultServiceManager;
{
AutoMutex_l(gDefaultServiceManagerLock);
if(gDefaultServiceManager==NULL){
gDefaultServiceManager=interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}
returngDefaultServiceManager;
}
任何一个进程在第一次调用defaultServiceManager的时候gDefaultServiceManager值为Null,所以该进程会通过ProcessState::self得到ProcessState实例。ProcessState将打开Binder驱动。
ProcessState.cpp
sp<ProcessState>ProcessState::self()
{
if(gProcess!=NULL)returngProcess;
AutoMutex_l(gProcessMutex);
if(gProcess==NULL)gProcess=newProcessState;
returngProcess;
}ProcessState::ProcessState()
:mDriverFD(open_driver())//打开/dev/binder驱动
...........................
{
}sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
if(supportsProcesses()){
returngetStrongProxyForHandle(0);
}else{
returngetContextObject(String16("default"),caller);
}
}
Android是支持Binder驱动的所以程序会调用getStrongProxyForHandle。这里handle为0,正好与Service_manager中的BINDER_SERVICE_MANAGER一致。
sp<IBinder>ProcessState::getStrongProxyForHandle(int32_thandle)
{
sp<IBinder>result;
AutoMutex_l(mLock);
handle_entry* e = lookupHandleLocked(handle);if (e != NULL) {
//WeneedtocreateanewBpBinderifthereisn'tcurrentlyone,ORwe
//areunabletoacquireaweakreferenceonthiscurrentone.Seecomment
//ingetWeakProxyForHandle()formoreinfoaboutthis.
IBinder*b=e->binder;//第一次调用该函数b为Null
if(b==NULL||!e->refs->attemptIncWeak(this)){
b=newBpBinder(handle);
e->binder=b;
if(b)e->refs=b->getWeakRefs();
result=b;
}else{
//Thislittlebitofnastynessistoallowustoaddaprimary
//referencetotheremoteproxywhenthisteamdoesn'thaveone
//butanotherteamissendingthehandletous.
result.force_set(b);
e->refs->decWeak(this);
}
}
returnresult;
}
第一次调用的时候b为Null所以会为b生成一BpBinder对象:
BpBinder::BpBinder(int32_thandle)
:mHandle(handle)
,mAlive(1)
,mObitsSent(0)
,mObituaries(NULL)
{
LOGV("Creating BpBinder %p handle %d\n", this, mHandle);extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);
}void IPCThreadState::incWeakHandle(int32_t handle)
{
LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n",handle);
mOut.writeInt32(BC_INCREFS);
mOut.writeInt32(handle);
}
getContextObject返回了一个BpBinder对象。
interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));template<typename INTERFACE>
inlinesp<INTERFACE>interface_cast(constsp<IBinder>&obj)
{
returnINTERFACE::asInterface(obj);
}
将这个宏扩展后最终得到的是:
sp<IServiceManager>IServiceManager::asInterface(constsp<IBinder>&obj)
{
sp<IServiceManager>intr;
if(obj!=NULL){
intr=static_cast<IServiceManager*>(
obj->queryLocalInterface(
IServiceManager::descriptor).get());
if(intr==NULL){
intr=newBpServiceManager(obj);
}
}
returnintr;
}
返回一个BpServiceManager对象,这里obj就是前面我们创建的BpBInder对象。client获取Service的远程IBinder接口
以CameraService为例(camera.cpp):
constsp<ICameraService>&Camera::getCameraService()
{
Mutex::Autolock_l(mLock);
if(mCameraService.get()==0){
sp<IServiceManager>sm=defaultServiceManager();
sp<IBinder>binder;
do{
binder=sm->getService(String16("media.camera"));
if(binder!=0)
break;
LOGW("CameraServicenotpublished,waiting...");
usleep(500000);//0.5s
}while(true);
if(mDeathNotifier==NULL){
mDeathNotifier=newDeathNotifier();
}
binder->linkToDeath(mDeathNotifier);
mCameraService=interface_cast<ICameraService>(binder);
}
LOGE_IF(mCameraService==0,"noCameraService!?");
returnmCameraService;
}
由前面的分析可知sm是BpCameraService对象://应该为BpServiceManager对象
virtualsp<IBinder>getService(constString16&name)const
{
unsignedn;
for(n=0;n<5;n++){
sp<IBinder>svc=checkService(name);
if(svc!=NULL)returnsvc;
LOGI("Waitingforsevice%s...\n",String8(name).string());
sleep(1);
}
returnNULL;
}
virtualsp<IBinder>checkService(constString16&name)const
{
Parceldata,reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION,data,&reply);
returnreply.readStrongBinder();
}
这里的remote就是我们前面得到BpBinder对象。所以checkService将调用BpBinder中的transact函数:
status_tBpBinder::transact(
uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
{
//Onceabinderhasdied,itwillnevercomebacktolife.
if(mAlive){
status_tstatus=IPCThreadState::self()->transact(
mHandle,code,data,reply,flags);
if(status==DEAD_OBJECT)mAlive=0;
returnstatus;
}
returnDEAD_OBJECT;
}
mHandle为0,BpBinder继续往下调用IPCThreadState:transact函数将数据发给与mHandle相关联的ServiceManagerProcess。
status_tIPCThreadState::transact(int32_thandle,
uint32_tcode,constParcel&data,
Parcel*reply,uint32_tflags)
{
............................................................
if(err==NO_ERROR){
LOG_ONEWAY(">>>>SENDfrompid%duid%d%s",getpid(),getuid(),
(flags&TF_ONE_WAY)==0?"READREPLY":"ONEWAY");
err=writeTransactionData(BC_TRANSACTION,flags,handle,code,data,NULL);
}
if(err!=NO_ERROR){
if(reply)reply->setError(err);
return(mLastError=err);
}
if((flags&TF_ONE_WAY)==0){
if(reply){
err=waitForResponse(reply);
}else{
ParcelfakeReply;
err=waitForResponse(&fakeReply);
}
..............................
returnerr;
}通过writeTransactionData构造要发送的数据
status_tIPCThreadState::writeTransactionData(int32_tcmd,uint32_tbinderFlags,
int32_thandle,uint32_tcode,constParcel&data,status_t*statusBuffer)
{
binder_transaction_data tr;tr.target.handle = handle; //这个handle将传递到service_manager
tr.code=code;
tr.flags=bindrFlags;
。。。。。。。。。。。。。。
}
waitForResponse将调用talkWithDriver与对Binderkernel进行读写操作。当Binderkernel接收到数据后,service_mananger线程的ThreadPool就会启动,service_manager查找到CameraService服务后调用binder_send_reply,将返回的数据写入Binderkernel,Binderkernel。
status_tIPCThreadState::waitForResponse(Parcel*reply,status_t*acquireResult)
{
int32_tcmd;
int32_t err;while (1) {
if((err=talkWithDriver())<NO_ERROR)break;
..............................................
}
status_tIPCThreadState::talkWithDriver(booldoReceive)
{
............................................
#ifdefined(HAVE_ANDROID_OS)
if(ioctl(mProcess->mDriverFD,BINDER_WRITE_READ,&bwr)>=0)
err=NO_ERROR;
else
err=-errno;
#else
err=INVALID_OPERATION;
#endif
...................................................
}
通过上面的ioctl系统函数中BINDER_WRITE_READ对binderkernel进行读写。