Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(4)
这个函数的实现很简单,就是把MediaPlayerService这个Binder实体的引用写到一个struct svcinfo结构体中,主要是它的名称和句柄值,然后插入到链接svclist的头部去。这样,Client来向Service Manager查询服务接口时,只要给定服务名称,Service Manger就可以返回相应的句柄值了。 这个函数执行完成后,返回到svcmgr_handler函数,函数的最后,将一个错误码0写到reply变量中去,表示一切正常: bio_put_uint32(reply,0); svcmgr_handler函数执行完成后,返回到binder_parse函数,执行下面语句: binder_send_reply(bs,&reply,txn->data,res); 我们看一下binder_send_reply的实现,从函数名就可以猜到它要做什么了,告诉Binder驱动程序,它完成了Binder驱动程序交给它的任务了。 voidbinder_send_reply(structbinder_state*bs, structbinder_io*reply, void*buffer_to_free, intstatus) { struct{ uint32_tcmd_free; void*buffer; uint32_tcmd_reply; structbinder_txntxn; }__attribute__((packed))data; data.cmd_free=BC_FREE_BUFFER; data.buffer=buffer_to_free; data.cmd_reply=BC_REPLY; data.txn.target=0; data.txn.cookie=0; data.txn.code=0; if(status){ data.txn.flags=TF_STATUS_CODE; data.txn.data_size=sizeof(int); data.txn.offs_size=0; data.txn.data=&status; data.txn.offs=0; }else{ data.txn.flags=0; data.txn.data_size=reply->data-reply->data0; data.txn.offs_size=((char*)reply->offs)-((char*)reply->offs0); data.txn.data=reply->data0; data.txn.offs=reply->offs0; } binder_write(bs,&data,sizeof(data)); } 从这里可以看出,binder_send_reply告诉Binder驱动程序执行BC_FREE_BUFFER和BC_REPLY命令,前者释放之前在binder_transaction分配的空间,地址为buffer_to_free,buffer_to_free这个地址是Binder驱动程序把自己在内核空间用的地址转换成用户空间地址再传给Service Manager的,所以Binder驱动程序拿到这个地址后,知道怎么样释放这个空间;后者告诉MediaPlayerService,它的addService操作已经完成了,错误码是0,保存在data.txn.data中。 再来看binder_write函数: intbinder_write(structbinder_state*bs,void*data,unsignedlen) { structbinder_write_readbwr; intres; bwr.write_size=len; bwr.write_consumed=0; bwr.write_buffer=(unsigned)data; bwr.read_size=0; bwr.read_consumed=0; bwr.read_buffer=0; res=ioctl(bs->fd,BINDER_WRITE_READ,&bwr); if(res<0){ fprintf(stderr,"binder_write:ioctlfailed(%s)\n", strerror(errno)); } returnres; } 这里可以看出,只有写操作,没有读操作,即read_size为0。 这里又是一个ioctl的BINDER_WRITE_READ操作。直入到驱动程序的binder_ioctl函数后,执行BINDER_WRITE_READ命令,这里就不累述了。 最后,从binder_ioctl执行到binder_thread_write函数,我们首先看第一个命令BC_FREE_BUFFER: int binder_thread_write(structbinder_proc*proc,structbinder_thread*thread, void__user*buffer,intsize,signedlong*consumed) { uint32_tcmd; void__user*ptr=buffer+*consumed; void__user*end=buffer+size; while(ptr<end&&thread->return_error==BR_OK){ if(get_user(cmd,(uint32_t__user*)ptr)) return-EFAULT; ptr+=sizeof(uint32_t); if(_IOC_NR(cmd)<ARRAY_SIZE(binder_stats.bc)){ binder_stats.bc[_IOC_NR(cmd)]++; proc->stats.bc[_IOC_NR(cmd)]++; thread->stats.bc[_IOC_NR(cmd)]++; } switch(cmd){ ...... caseBC_FREE_BUFFER:{ void__user*data_ptr; structbinder_buffer*buffer; if(get_user(data_ptr,(void*__user*)ptr)) return-EFAULT; ptr+=sizeof(void*); buffer=binder_buffer_lookup(proc,data_ptr); if(buffer==NULL){ binder_user_error("binder:%d:%d" "BC_FREE_BUFFERu%pnomatch\n", proc->pid,thread->pid,data_ptr); break; } if(!buffer->allow_user_free){ binder_user_error("binder:%d:%d" "BC_FREE_BUFFERu%pmatched" "unreturnedbuffer\n", proc->pid,thread->pid,data_ptr); break; } if(binder_debug_mask&BINDER_DEBUG_FREE_BUFFER) printk(KERN_INFO"binder:%d:%dBC_FREE_BUFFERu%pfoundbuffer%dfor%stransaction\n", proc->pid,thread->pid,data_ptr,buffer->debug_id, buffer->transaction?"active":"finished"); if(buffer->transaction){ buffer->transaction->buffer=NULL; buffer->transaction=NULL; } if(buffer->async_transaction&&buffer->target_node){ BUG_ON(!buffer->target_node->has_async_transaction); if(list_empty(&buffer->target_node->async_todo)) buffer->target_node->has_async_transaction=0; else list_move_tail(buffer->target_node->async_todo.next,&thread->todo); } binder_transaction_buffer_release(proc,buffer,NULL); binder_free_buf(proc,buffer); break; } ...... *consumed=ptr-buffer; } return0; } 首先通过看这个语句: get_user(data_ptr,(void*__user*)ptr) 这个是获得要删除的Buffer的用户空间地址,接着通过下面这个语句来找到这个地址对应的struct binder_buffer信息: buffer=binder_buffer_lookup(proc,data_ptr); 因为这个空间是前面在binder_transaction里面分配的,所以这里一定能找到。 最后,就可以释放这块内存了: binder_transaction_buffer_release(proc,buffer,NULL); binder_free_buf(proc,buffer); 再来看另外一个命令BC_REPLY: int binder_thread_write(structbinder_proc*proc,structbinder_thread*thread, void__user*buffer,intsize,signedlong*consumed) { uint32_tcmd; void__user*ptr=buffer+*consumed; void__user*end=buffer+size; while(ptr<end&&thread->return_error==BR_OK){ if(get_user(cmd,(uint32_t__user*)ptr)) return-EFAULT; ptr+=sizeof(uint32_t); if(_IOC_NR(cmd)<ARRAY_SIZE(binder_stats.bc)){ binder_stats.bc[_IOC_NR(cmd)]++; proc->stats.bc[_IOC_NR(cmd)]++; thread->stats.bc[_IOC_NR(cmd)]++; } switch(cmd){ ...... caseBC_TRANSACTION: caseBC_REPLY:{ structbinder_transaction_datatr; if(copy_from_user(&tr,ptr,sizeof(tr))) return-EFAULT; ptr+=sizeof(tr); binder_transaction(proc,thread,&tr,cmd==BC_REPLY); break; } ...... *consumed=ptr-buffer; } return0; } 又再次进入到binder_transaction函数: staticvoid binder_transaction(structbinder_proc*proc,structbinder_thread*thread, structbinder_transaction_data*tr,intreply) { structbinder_transaction*t; structbinder_work*tcomplete; size_t*offp,*off_end; structbinder_proc*target_proc; structbinder_thread*target_thread=NULL; structbinder_node*target_node=NULL; structlist_head*target_list; wait_queue_head_t*target_wait; structbinder_transaction*in_reply_to=NULL; structbinder_transaction_log_entry*e; uint32_treturn_error; ...... if(reply){ in_reply_to=thread->transaction_stack; if(in_reply_to==NULL){ ...... return_error=BR_FAILED_REPLY; gotoerr_empty_call_stack; } binder_set_nice(in_reply_to->saved_priority); if(in_reply_to->to_thread!=thread){ ....... gotoerr_bad_call_stack; } thread->transaction_stack=in_reply_to->to_parent; target_thread=in_reply_to->from; if(target_thread==NULL){ return_error=BR_DEAD_REPLY; gotoerr_dead_binder; } if(target_thread->transaction_stack!=in_reply_to){ ...... return_error=BR_FAILED_REPLY; in_reply_to=NULL; target_thread=NULL; gotoerr_dead_binder; } target_proc=target_thread->proc; }else{ ...... } if(target_thread){ e->to_thread=target_thread->pid; target_list=&target_thread->todo; target_wait=&target_thread->wait; }else{ ...... } /*TODO:reuseincomingtransactionforreply*/ t=kzalloc(sizeof(*t),GFP_KERNEL); if(t==NULL){ return_error=BR_FAILED_REPLY; gotoerr_alloc_t_failed; } tcomplete=kzalloc(sizeof(*tcomplete),GFP_KERNEL); if(tcomplete==NULL){ return_error=BR_FAILED_REPLY; gotoerr_alloc_tcomplete_failed; } if(!reply&&!(tr->flags&TF_ONE_WAY)) t->from=thread; else t->from=NULL; t->sender_euid=proc->tsk->cred->euid; t->to_proc=target_proc; t->to_thread=target_thread; t->code=tr->code; t->flags=tr->flags; t->priority=task_nice(current); t->buffer=binder_alloc_buf(target_proc,tr->data_size, tr->offsets_size,!reply&&(t->flags&TF_ONE_WAY)); if(t->buffer==NULL){ return_error=BR_FAILED_REPLY; gotoerr_binder_alloc_buf_failed; } t->buffer->allow_user_free=0; t->buffer->debug_id=t->debug_id; t->buffer->transaction=t; t->buffer->target_node=target_node; if(target_node) binder_inc_node(target_node,1,0,NULL); offp=(size_t*)(t->buffer->data+ALIGN(tr->data_size,sizeof(void*))); if(copy_from_user(t->buffer->data,tr->data.ptr.buffer,tr->data_size)){ binder_user_error("binder:%d:%dgottransactionwithinvalid" "dataptr\n",proc->pid,thread->pid); return_error=BR_FAILED_REPLY; gotoerr_copy_data_failed; } if(copy_from_user(offp,tr->data.ptr.offsets,tr->offsets_size)){ binder_user_error("binder:%d:%dgottransactionwithinvalid" "offsetsptr\n",proc->pid,thread->pid); return_error=BR_FAILED_REPLY; gotoerr_copy_data_failed; } ...... if(reply){ BUG_ON(t->buffer->async_transaction!=0); binder_pop_transaction(target_thread,in_reply_to); }elseif(!(t->flags&TF_ONE_WAY)){ ...... }else{ ...... } t->work.type=BINDER_WORK_TRANSACTION; list_add_tail(&t->work.entry,target_list); tcomplete->type=BINDER_WORK_TRANSACTION_COMPLETE; list_add_tail(&tcomplete->entry,&thread->todo); if(target_wait) wake_up_interruptible(target_wait); return; ...... } 注意,这里的reply为1,我们忽略掉其它无关代码。 前面Service Manager正在binder_thread_read函数中被MediaPlayerService启动后进程唤醒后,在最后会把当前处理完的事务放在thread->transaction_stack中: if(cmd==BR_TRANSACTION&&!(t->flags&TF_ONE_WAY)){ t->to_parent=thread->transaction_stack; t->to_thread=thread; thread->transaction_stack=t; } 所以,这里,首先是把它这个binder_transaction取回来,并且放在本地变量in_reply_to中: in_reply_to=thread->transaction_stack; 接着就可以通过in_reply_to得到最终发出这个事务请求的线程和进程: target_thread=in_reply_to->from; target_proc=target_thread->proc; 然后得到target_list和target_wait: target_list=&target_thread->todo; target_wait=&target_thread->wait; 下面这一段代码: /*TODO:reuseincomingtransactionforreply*/ t=kzalloc(sizeof(*t),GFP_KERNEL); if(t==NULL){ return_error=BR_FAILED_REPLY; gotoerr_alloc_t_failed; } tcomplete=kzalloc(sizeof(*tcomplete),GFP_KERNEL); if(tcomplete==NULL){ return_error=BR_FAILED_REPLY; gotoerr_alloc_tcomplete_failed; } if(!reply&&!(tr->flags&TF_ONE_WAY)) t->from=thread; else t->from=NULL; t->sender_euid=proc->tsk->cred->euid; t->to_proc=target_proc; t->to_thread=target_thread; t->code=tr->code; t->flags=tr->flags; t->priority=task_nice(current); t->buffer=binder_alloc_buf(target_proc,tr->data_size, tr->offsets_size,!reply&&(t->flags&TF_ONE_WAY)); if(t->buffer==NULL){ return_error=BR_FAILED_REPLY; gotoerr_binder_alloc_buf_failed; } t->buffer->allow_user_free=0; t->buffer->debug_id=t->debug_id; t->buffer->transaction=t; t->buffer->target_node=target_node; if(target_node) binder_inc_node(target_node,1,0,NULL); offp=(size_t*)(t->buffer->data+ALIGN(tr->data_size,sizeof(void*))); if(copy_from_user(t->buffer->data,tr->data.ptr.buffer,tr->data_size)){ binder_user_error("binder:%d:%dgottransactionwithinvalid" "dataptr\n",proc->pid,thread->pid); return_error=BR_FAILED_REPLY; gotoerr_copy_data_failed; } if(copy_from_user(offp,tr->data.ptr.offsets,tr->offsets_size)){ binder_user_error("binder:%d:%dgottransactionwithinvalid" "offsetsptr\n",proc->pid,thread->pid); return_error=BR_FAILED_REPLY; gotoerr_copy_data_failed; } 我们在前面已经分析过了,这里不再重复。但是有一点要注意的是,这里target_node为NULL,因此,t->buffer->target_node也为NULL。 函数本来有一个for循环,用来处理数据中的Binder对象,这里由于没有Binder对象,所以就略过了。到了下面这句代码: binder_pop_transaction(target_thread,in_reply_to); 我们看看做了什么事情 staticvoid binder_pop_transaction( structbinder_thread*target_thread,structbinder_transaction*t) { if(target_thread){ BUG_ON(target_thread->transaction_stack!=t); BUG_ON(target_thread->transaction_stack->from!=target_thread); target_thread->transaction_stack= target_thread->transaction_stack->from_parent; t->from=NULL; } t->need_reply=0; if(t->buffer) t->buffer->transaction=NULL; kfree(t); binder_stats.obj_deleted[BINDER_STAT_TRANSACTION]++; } 由于到了这里,已经不需要in_reply_to这个transaction了,就把它删掉。 回到binder_transaction函数: t->work.type=BINDER_WORK_TRANSACTION; list_add_tail(&t->work.entry,target_list); tcomplete->type=BINDER_WORK_TRANSACTION_COMPLETE; list_add_tail(&tcomplete->entry,&thread->todo); 和前面一样,分别把t和tcomplete分别放在target_list和thread->todo队列中,这里的target_list指的就是最初调用IServiceManager::addService的MediaPlayerService的Server主线程的的thread->todo队列了,而thread->todo指的是Service Manager中用来回复IServiceManager::addService请求的线程。 最后,唤醒等待在target_wait队列上的线程了,就是最初调用IServiceManager::addService的MediaPlayerService的Server主线程了,它最后在binder_thread_read函数中睡眠在thread->wait上,就是这里的target_wait了: if(target_wait) wake_up_interruptible(target_wait); 这样,Service Manger回复调用IServiceManager::addService请求就算完成了,重新回到frameworks/base/cmds/servicemanager/binder.c文件中的binder_loop函数等待下一个Client请求的到来。事实上,Service Manger回到binder_loop函数再次执行ioctl函数时候,又会再次进入到binder_thread_read函数。这时个会发现thread->todo不为空,这是因为刚才我们调用了: list_add_tail(&tcomplete->entry,&thread->todo); 把一个工作项tcompelete放在了在thread->todo中,这个tcompelete的type为BINDER_WORK_TRANSACTION_COMPLETE,因此,Binder驱动程序会执行下面操作: switch(w->type){ caseBINDER_WORK_TRANSACTION_COMPLETE:{ cmd=BR_TRANSACTION_COMPLETE; if(put_user(cmd,(uint32_t__user*)ptr)) return-EFAULT; ptr+=sizeof(uint32_t); list_del(&w->entry); kfree(w); }break; ...... } binder_loop函数执行完这个ioctl调用后,才会在下一次调用ioctl进入到Binder驱动程序进入休眠状态,等待下一次Client的请求。 上面讲到调用IServiceManager::addService的MediaPlayerService的Server主线程被唤醒了,于是,重新执行binder_thread_read函数: staticint binder_thread_read(structbinder_proc*proc,structbinder_thread*thread, void__user*buffer,intsize,signedlong*consumed,intnon_block) { void__user*ptr=buffer+*consumed; void__user*end=buffer+size; intret=0; intwait_for_proc_work; if(*consumed==0){ if(put_user(BR_NOOP,(uint32_t__user*)ptr)) return-EFAULT; ptr+=sizeof(uint32_t); } retry: wait_for_proc_work=thread->transaction_stack==NULL&&list_empty(&thread->todo); ...... if(wait_for_proc_work){ ...... }else{ if(non_block){ if(!binder_has_thread_work(thread)) ret=-EAGAIN; }else ret=wait_event_interruptible(thread->wait,binder_has_thread_work(thread)); } ...... while(1){ uint32_tcmd; structbinder_transaction_datatr; structbinder_work*w; structbinder_transaction*t=NULL; if(!list_empty(&thread->todo)) w=list_first_entry(&thread->todo,structbinder_work,entry); elseif(!list_empty(&proc->todo)&&wait_for_proc_work) w=list_first_entry(&proc->todo,structbinder_work,entry); else{ if(ptr-buffer==4&&!(thread->looper&BINDER_LOOPER_STATE_NEED_RETURN))/*nodataadded*/ gotoretry; break; } ...... switch(w->type){ caseBINDER_WORK_TRANSACTION:{ t=container_of(w,structbinder_transaction,work); }break; ...... } if(!t) continue; BUG_ON(t->buffer==NULL); if(t->buffer->target_node){ ...... }else{ tr.target.ptr=NULL; tr.cookie=NULL; cmd=BR_REPLY; } tr.code=t->code; tr.flags=t->flags; tr.sender_euid=t->sender_euid; if(t->from){ ...... }else{ tr.sender_pid=0; } tr.data_size=t->buffer->data_size; tr.offsets_size=t->buffer->offsets_size; tr.data.ptr.buffer=(void*)t->buffer->data+proc->user_buffer_offset; tr.data.ptr.offsets=tr.data.ptr.buffer+ALIGN(t->buffer->data_size,sizeof(void*)); if(put_user(cmd,(uint32_t__user*)ptr)) return-EFAULT; ptr+=sizeof(uint32_t); if(copy_to_user(ptr,&tr,sizeof(tr))) return-EFAULT; ptr+=sizeof(tr); ...... list_del(&t->work.entry); t->buffer->allow_user_free=1; if(cmd==BR_TRANSACTION&&!(t->flags&TF_ONE_WAY)){ ...... }else{ t->buffer->transaction=NULL; kfree(t); binder_stats.obj_deleted[BINDER_STAT_TRANSACTION]++; } break; } done: ...... return0; } 在while循环中,从thread->todo得到w,w->type为BINDER_WORK_TRANSACTION,于是,得到t。从上面可以知道,Service Manager反回了一个0回来,写在t->buffer->data里面,现在把t->buffer->data加上proc->user_buffer_offset,得到用户空间地址,保存在tr.data.ptr.buffer里面,这样用户空间就可以访问这个返回码了。由于cmd不等于BR_TRANSACTION,这时就可以把t删除掉了,因为以后都不需要用了。 执行完这个函数后,就返回到binder_ioctl函数,执行下面语句,把数据返回给用户空间: if(copy_to_user(ubuf,&bwr,sizeof(bwr))){ ret=-EFAULT; gotoerr; } 接着返回到用户空间IPCThreadState::talkWithDriver函数,最后返回到IPCThreadState::waitForResponse函数,最终执行到下面语句: status_tIPCThreadState::waitForResponse(Parcel*reply,status_t*acquireResult) { int32_tcmd; int32_terr; while(1){ if((err=talkWithDriver())<NO_ERROR)break; ...... cmd=mIn.readInt32(); ...... switch(cmd){ ...... caseBR_REPLY: { binder_transaction_datatr; err=mIn.read(&tr,sizeof(tr)); LOG_ASSERT(err==NO_ERROR,"NotenoughcommanddataforbrREPLY"); if(err!=NO_ERROR)gotofinish; if(reply){ if((tr.flags&TF_STATUS_CODE)==0){ reply->ipcSetDataReference( reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<constsize_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(size_t), freeBuffer,this); }else{ ...... } }else{ ...... } } gotofinish; ...... } } finish: ...... returnerr; } 注意,这里的tr.flags等于0,这个是在上面的binder_send_reply函数里设置的。最终把结果保存在reply了: reply->ipcSetDataReference( reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<constsize_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(size_t), freeBuffer,this); 这个函数我们就不看了,有兴趣的读者可以研究一下。 从这里层层返回,最后回到MediaPlayerService::instantiate函数中。 至此,IServiceManager::addService终于执行完毕了。这个过程非常复杂,但是如果我们能够深刻地理解这一过程,将能很好地理解Binder机制的设计思想和实现过程。这里,对IServiceManager::addService过程中MediaPlayerService、ServiceManager和BinderDriver之间的交互作一个小结: 回到frameworks/base/media/mediaserver/main_mediaserver.cpp文件中的main函数,接下去还要执行下面两个函数: ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); 首先看ProcessState::startThreadPool函数的实现: voidProcessState::startThreadPool() { AutoMutex_l(mLock); if(!mThreadPoolStarted){ mThreadPoolStarted=true; spawnPooledThread(true); } } 这里调用spwanPooledThread: voidProcessState::spawnPooledThread(boolisMain) { if(mThreadPoolStarted){ int32_ts=android_atomic_add(1,&mThreadPoolSeq); charbuf[32]; sprintf(buf,"BinderThread#%d",s); LOGV("Spawningnewpooledthread,name=%s\n",buf); sp<Thread>t=newPoolThread(isMain); t->run(buf); } } 这里主要是创建一个线程,PoolThread继续Thread类,Thread类定义在frameworks/base/libs/utils/Threads.cpp文件中,其run函数最终调用子类的threadLoop函数,这里即为PoolThread::threadLoop函数: virtualboolthreadLoop() { IPCThreadState::self()->joinThreadPool(mIsMain); returnfalse; } 这里和frameworks/base/media/mediaserver/main_mediaserver.cpp文件中的main函数一样,最终都是调用了IPCThreadState::joinThreadPool函数,它们的区别是,一个参数是true,一个是默认值false。我们来看一下这个函数的实现: voidIPCThreadState::joinThreadPool(boolisMain) { LOG_THREADPOOL("****THREAD%p(PID%d)ISJOININGTHETHREADPOOL\n",(void*)pthread_self(),getpid()); mOut.writeInt32(isMain?BC_ENTER_LOOPER:BC_REGISTER_LOOPER); ...... status_tresult; do{ int32_tcmd; ....... //nowgetthenextcommandtobeprocessed,waitingifnecessary result=talkWithDriver(); if(result>=NO_ERROR){ size_tIN=mIn.dataAvail(); if(IN<sizeof(int32_t))continue; cmd=mIn.readInt32(); ...... } result=executeCommand(cmd); } ...... }while(result!=-ECONNREFUSED&&result!=-EBADF); ....... mOut.writeInt32(BC_EXIT_LOOPER); talkWithDriver(false); } 这个函数最终是在一个无穷循环中,通过调用talkWithDriver函数来和Binder驱动程序进行交互,实际上就是调用talkWithDriver来等待Client的请求,然后再调用executeCommand来处理请求,而在executeCommand函数中,最终会调用BBinder::transact来真正处理Client的请求: status_tIPCThreadState::executeCommand(int32_tcmd) { BBinder*obj; RefBase::weakref_type*refs; status_tresult=NO_ERROR; switch(cmd){ ...... caseBR_TRANSACTION: { binder_transaction_datatr; result=mIn.read(&tr,sizeof(tr)); ...... Parcelreply; ...... if(tr.target.ptr){ sp<BBinder>b((BBinder*)tr.cookie); conststatus_terror=b->transact(tr.code,buffer,&reply,tr.flags); if(error<NO_ERROR)reply.setError(error); }else{ conststatus_terror=the_context_object->transact(tr.code,buffer,&reply,tr.flags); if(error<NO_ERROR)reply.setError(error); } ...... } break; ....... } if(result!=NO_ERROR){ mLastError=result; } returnresult; } 接下来再看一下BBinder::transact的实现: status_tBBinder::transact( uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags) { data.setDataPosition(0); status_terr=NO_ERROR; switch(code){ casePING_TRANSACTION: reply->writeInt32(pingBinder()); break; default: err=onTransact(code,data,reply,flags); break; } if(reply!=NULL){ reply->setDataPosition(0); } returnerr; } 最终会调用onTransact函数来处理。在这个场景中,BnMediaPlayerService继承了BBinder类,并且重载了onTransact函数,因此,这里实际上是调用了BnMediaPlayerService::onTransact函数,这个函数定义在frameworks/base/libs/media/libmedia/IMediaPlayerService.cpp文件中: status_tBnMediaPlayerService::onTransact( uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags) { switch(code){ caseCREATE_URL:{ ...... }break; caseCREATE_FD:{ ...... }break; caseDECODE_URL:{ ...... }break; caseDECODE_FD:{ ...... }break; caseCREATE_MEDIA_RECORDER:{ ...... }break; caseCREATE_METADATA_RETRIEVER:{ ...... }break; caseGET_OMX:{ ...... }break; default: returnBBinder::onTransact(code,data,reply,flags); } } 至此,我们就以MediaPlayerService为例,完整地介绍了Android系统进程间通信Binder机制中的Server启动过程。Server启动起来之后,就会在一个无穷循环中等待Client的请求了。在下一篇文章中,我们将介绍Client如何通过Service Manager远程接口来获得Server远程接口,进而调用Server远程接口来使用Server提供的服务,敬请关注。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/964542,如需转载请自行联系原作者