您的位置:首页 > 移动开发 > Android开发

Android的Binder机制浅析

2010-06-03 08:55 387 查看
1. 引言

一般实际的软件系统中进程间通信(IPC)的实现方法有命名管道(named pipe),共享内存(shared memory),消息队列(message queue),Socket等方法。在Android的框架(Framework)中,以Binder作为框架内进程间(通常如服务和客户间)通信的主要实现手段。这可能是出于效率和软件架构考虑。Binder通信的底层基础是Binder设备,本文通过一些实例简要介绍基于Binder通信的流程,由于整个机制,尤其是驱动和一些数据封装部分相当复杂,本文也仅仅关注了其主体的流程,难免有疏漏和错误。

2. Binder相关模块及其流程

Binder通信主要涉及以下文件:
进程状态对象:
include/utils/ProcessState.h, lib/utils/ProcessState.cpp
IPC通信机制和状态:
include/utils/IPCThreadState.h, lib/utils/ProcessState.cpp
Binder基础类:
include/utils/Binder.h,(以及一些派生类等)
(本文不加说明,相对目录均从/frameworks/base出发)

设备驱动模块:
Binder驱动模块位于Android根目录下/kernel/drivers/misc/binder.c中。

2.1 主要模块概览

图1显示了Framework中模块。其中XXX表示某具体应用。例如对Surface,其接口就是ISurface,本地调用端就是BpSurface,实现端就是BnSurface;对ServiceManager其接口就是IServiceManager,本地调用端就是BpServiceManager,实现端就是BnServiceManager。





图1 IPC-Binder相关对象继承关系
接口IXXX规定了这个应用需要实现的一些方法,例如ISurface中就定义了以下方法:

方法名说明
registerBuffers注册Buffer
postBuffer输送Buffer
unregisterBuffers注销Buffer
createOverlay创建叠层
以Surface应用为例,远端实现侧(进程)是一个Surface操作的具体实现。而在另一个具体的进程中只要通过创建和使用BpSurface,就能够调用这个远端进程的功能。
于是BpXXX,在这里即BpSurface,由于继承了ISurface,必须也实现这些方法。而通常BpXXX是本地调用远端具体实现的入口,因此在这其中通常是启动IPC,传入和传出数据和参数的过程,这其中mRemote(BpBinder对象)是媒介,详见后续讨论。
而BnXXX,即BnSurface,同样也继承了IServiceManager,也实现这些方法。而BnXXX(或其派生类),必须真正实现这些方法的具体工作,因为它是被BpXXX调用的。

又如SurfaceFlingerClient,其接口ISurfaceFlingerClient定义如下方法:

方法名说明
getControlBlocks获得控制块
createSurface创建一个Surface对象(Bp, Bn侧)
destroySurface销毁一个Surface对象
setState设置状态
而媒体播放器服务MediaPlayerService,其接口IMediaPlayerService定义如下方法:

方法名说明
createMediaRecorer创建一个媒体录制器(MediaRecorder)
createMetadataRetriever创建一个元数据读取器(MetadataRetriever)
create创建一个媒体播放器(MediaPlayer)
decode解码一个流
同样服务管理模块ServiceManager也是一个基于Binder的应用,接口IServiceManager定义了如下方法:

方法名说明
getService获得一个服务
checkService查询服务
addService添加一个服务
listServices列举服务
2.2 Binder初始化

由于Binder的基础是Binder设备,因此设备的启动和配置是首要操作。
首先一个是Binder处理进程,它是android启动后第一个运行的binder相关程序。以下代码主要在cmds/serviceManager/binder.c中。以下是代码分析片段:

1: int main(int argc, char **argv)


2: {


3:     struct binder_state *bs;


4:     void *svcmgr = BINDER_SERVICE_MANAGER;    //一个NULL指针


5:


6:     bs = binder_open(mapsize = 128*1024)


7:     {


8:         …


9:         bs->fd = open("/dev/binder", O_RDWR);


10:         …


11:         bs->mapsize = mapsize;


12:         bs->mapped = mmap(NULL, mpasize, PROT_READ, MAP_PRIVATE, bs->fd, 0);


13:         …


14:     }


15:


16:     binder_become_context_manager(bs)


17:     {


18:         // 将本进程在内核中注册为context manager


19:         ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);


20:     }


21:


22:     svcmgr_handle = svcmgr;


23:     binder_loop(bs, svcmgr_handler)    // binder消息分发的关键循环


24:     {


25:         …


26:         for(;;) {


27:             …


28:             // 一般阻塞再此,直到有消息送达(阻塞点1),详见激活点1


29:             ioctl(bs->fd, BINDER_WRITE_READ, &bwr)


30:             {


31:                 …


32:                 binder_thread_write(…) { …}


33:                 binder_thread_read(…)


34:                 {


35:                     …激活后,相应处理中会在ptr所指buffer中将cmd设置为


36:                     BR_TRANSACTION


37:                 }


38:                 …


39:             }


40:


41:             // 解析消息


42:             binder_parse(bs, bio = 0, ptr=readbuf, size = bwr.read_consumed,


43:                         func = svcmgr_handler)


44:             {


45:                 while (解析readbuf未完)


46:                 {


47:                     cmd = *ptr++;


48:                     switch(cmd)


49:                     {


50:                     …


51:                     case BR_TRANSACTION:


52:                         func {=svcmgr_handler}(bs, txn, &msg, &reply)


53:                         {


54:                             …


55:                             switch(txn->code)


56:                             {


57:                             case SVC_MGR_GET_SERVICE: …


58:                             case SVC_MGR_CHECK_SERVICE: …


59:                             …


60:                             }


61:                             …


62:                         }


63:                         binder_send_reply(bs, &reply, txn->data, res)


64:                         {


65:                             data= …


66:                             binder_write(bs, &data, sizeof(data))


67:                             {


68:                                 ioctl(bs->fd, BINDER_WRITE_READ, &bwr)


69:                             }


70:                         }


71:                     }


72:                 }


73:             }


74:         }


75:     }


76:     return 0;


77: }


2.3 Runtime初始化

以下的服务进程和2.2介绍的类似,也是实现了ServiceManager的接口功能,只是它是用C++实现的,并且其本身也做成了Binder类型。
因此,它可能是在上述2.2初始化之后最先加入的服务,而此后它将服务于维护其他服务。同样它也注册成Context Manager,这样在客户侧调用时无需制定具体的对象句柄。
以下程序位于cmds/runtime/main_runtime.cpp。

1: int main(…)


2: {


3:     …


4:     boot_init()


5:   {


6:         proc = ProcessState::self();


7:         proc->becomeContextManager(contextChecker, NULL)


8:         {


9:             …


10:             // 本进程变为Context Manager,接受后续的Binder处理


11:             ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);


12:             …


13:         }


14:


15:       sm = new BServiceManager;


16:


17:         proc->setContextObject(IBinder object = sm)


18:         {


19:             setContextObject(sm, "default")


20:             {


21:               mContexts.add("default", sm)


22:                 {


23:                     装入映射表mContexts中…


24:                 }


25:             }


26:         }


27:         …


28:         run(…)


29:         {


30:             …


31:             IPCThreadState::self()->joinThreadPool()


32:             {


33:                 等待消息,过程类似2.7中的讨论


34:             }


35:         }


36:     }


37:     …


38: }


BServiceManager实现BnServiceManager,由于ServiceManager服务程序作为ContextManager,因此后续在defaultServiceManager()上进行IServiceManager调用(如调用getService())都将定向到这个对象,而BServiceManager则维护了系统中的所有服务。

2.4 Bp对象的创建

Bp相关类型在framework中通过宏定义实现。这个宏定义在include/utils/IInterface.h中以DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE命名。在相关的类定义中加入,例如在BpSurface这个例子中,它在ISurface.cpp中出现。

1: sp BpSurfaceFlingerClient::createSurface(..)


2: {


3:     …


4:     data上设置参数


5:   mRemote->transact(CREATE_SURFACE, data, &reply)


6:     {


7:         … IPC调用到Bn侧功能并返回


8:     }


9:     …


10:     sp binder = reply.readStrongBinder()


11:     {


12:         unflatten_binder(proc=ProcessState::self(), *this, sp* out = &val)


13:         {


14:           // 从in中取出flat_binder_object


15:           flat_binder_object *flat = in.readObject(false);


16:           if (flat)


17:             {


18:                 switch(flat->type)


19:                 {


20:                 …


21:               case BINDER_TYPE_HANDLE:    // 本节注释1


22:                     *out = proc->getStrongProxyForHandle(flat->handle)


23:                     /* ProcessState:: getStrongProxyForHandle() */


24:                     {


25:                         // 查表获得一个表项,若首次则创建一个表项


26:                         e = lookupHandleLocked(handle);


27:                         if (e != NULL) {


28:                             IBinder * b = e->binder;


29:                             if (b == NULL || …)


30:                             {    // 初次e->binder为空


31:                                 e->binder = b = new BpBinder(handle)


32:                                 { mHandle = handle; }


33:                                 …


34:                                 result = b;


35:                             }


36:                         }


37:                         return result;


38:                     }


39:                     return finish_unflatten_binder(NULL, *flat, in);


40:    }


41:             }


42:         }


43:         return val;


44:     }


45:     return interface_cast(binder)        // 上述宏定义的展开


46:     {


47:         return sp ISurface::asInterface(binder)


48:         {


49:             sp intr;


50:             if (binder != NULL)


51:             {


52:                 …


53:                 intr = new BpSurface(binder)


54:                 {


55:                     基类创建:BpRefBase(binder)


56:                     {


57:                         mRemote = binder.get();    // 即刚创建的BpBinder


58:                     }


59:                 }


60:             }


61:         }


62:     }


63: }


可见BpSurfaceFlingerClient的作用之一是创建BpSurface对象。两者都在客户端(同一进程中)。

-----
【注释1】 在binder_transaction传递(ioctl在BINDER_WRITE_READ的BC_REPLY返回时,详见后续章节)中会将扁平处理的binder信息flat_binder_object中的类型从BINDER_TYPE_BINDER转换为BINDER_TYPE_HANDLE,而具体的handle是从底层对象注册用的红黑树上取出的唯一handle号,这样Bp侧用这个handle号和Bn侧的具体对象对应。

2.5 Bn对象的创建

而在Bn侧BnSurfaceFlingerClient::onTransact处理上述mRemote->transact的过程:

1: BnSurfaceFlingerClient::onTransact(…)


2: {


3:     …


4:     switch(code) {


5:   case CREATE_SURFACE:


6:         从data上获取参数


7:         sp s = BClient::createSurface(…)


8:         {


9:             …


10:             创建一个Bn侧的ISurface实体对象s


11:             (BnSurface类型,具体如LayerBuffer::SurfaceBuffer)


12:             …


13:             sBinder = s->IInterface::asBinder()


14:           {


15:               BnInterface::onAsBinder()


16:               {


17:                     return this;


18:                 }


19:             }


20:             reply->writeStrongBinder(sBinder)


21:           {


22:                 flatten_binder(ProcessState::self(), binder= sBinder, out = this = reply)


23:                 {


24:                     flat_binder_object obj;


25:                     obj.flags = …


26:                     if (sBinder!= NULL)


27:                     {


28:                         local = binder->localBinder() { return this; }


29:                         if (!local)…


30:                         else


31:                         {


32:                             obj.type = BINDER_TYPE_BINDER;


33:                             obj.binder = local->getWeakRefs();


34:                             obj.cookie = local;    // 这个在后续访问操作使用


35:                         }


36:                     }


37:                     … 其他分支略


38:


39:                     return finish_flatten_binder(sBinder, obj, out)


40:        {


41:                         out->writeObject(obj, nullMetaData = false)


42:                         {


43:                             …将obj数据写到out这个Parcel对象中


44:                         }


45:                     }


46:                 }


47:             }


48:             // 此后reply这个Parcel将通过IPC传回客户端


49:         }


50:         …


51:     }


52: }


上述客户端和远端代码基本展示了Surface的创建过程。Bp和Bn侧的Surface创建完成后才有后续Surface的具体运作。

2.6 BpSurface运作

以前面提到的ISurface上的postBuffer接口的工作为例。这部分将深一些到IPC 事务(transaction)作业内部。其实前一节的Surface的创建过程已经调用了ISurfaceFlingerClient::createSurface接口,已经走了一遍类似的transaction事务流程,而前一节主要以BpSurface和BnSurface为例介绍在IPC流程的前提——两侧的建立为目的,在这里再对此后的事务操作进行详细介绍。
从BpSurface出发:

1: void BpSurface::postBuffer(offset)


2: {


3:     data.writeInterfacetoken(ISurface::getInterfaceDescriptor());    // ISurface接口描述符


4:     data.writeInt32(offset);


5:   mRemote->transact(code =POST_BUFFER, data, reply = &reply, 


6:                       flags = IBinder::FLAG_ONEWAY)    // FLAG_ONEWAY=1


7:     (mRemote即刚才建立的BpBinder对象,即BpBinder::transact(..))


8:     {


9:         …


10:         IPCThreadState::self()->transact(handle = mHandle, code, data, reply, flags)


11:         {    // handle是对应Bn侧Surface对象的有效值


12:             …


13:             writeTransactionData(cmd = BC_TRANSACTION, flags, handle,


14:                                code, data, NULL)


15:           {


16:               binder_transaction_data tr;


17:                 tr.target.handle = handle;


18:                 tr.code = code; tr.flags = flags;


19:                 ...


20:                 mOut.writeInt32(cmd)


21:               mOut.write(&tr, sizeof(tr));


22:                 …


23:             }


24:             …


25:             waitForResponse(reply = NULL, acquireResult = NULL)    // 不需要返回值


26:             {


27:                 while(1)


28:                 {


29:                     talkWithDriver()


30:                     {


31:                         …


32:                         ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)


33:                         …


34:                     }


35:                     … 处理返回值


36:                 }


37:             }


38:       }


39:         …


40:     }


41: }


上述ioctl将调用请求做成通过Binder发送到远端。其过程在后续章节介绍。

2.7 Binder驱动概要

在/kernel/drivers/misc/binder.c的Binder设备驱动中,定义了以下函数,它在内核中处理上述ioctl调用,完成Binder的功能。

1: static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)


2: {


3:     …


4:     // 以下将本函数调用者进程挂起(如上述BpSurface所在进程),直到处理完返回


5:   wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);


6:


7:     // 进程私有数据


8:     binder_proc proc = filp->private_data;


9:     // 获得调用者进程的线程池数据结构


10:     binder_thread *thread = binder_get_thread(proc);


11:     …


12:     switch(cmd)


13:     {


14:   case BINDER_WRITE_READ:


15:       …


16:       // 从用户空间将bind_write_read参数复制到bwr


17:         copy_from_user(&bwr, ubuf, sizeof(bwr);


18:         …


19:         binder_thread_write(proc, thread, bwr.write_buffer, bwr.write_size,


20:                             bwr.write_consumed)


21:       {


22:             while (处理bwr.write_buffer未完成)


23:             {


24:                 // 从用户空间获取cmd数据到内核空间


25:                 get_user(cmd, (uint32_t __user *)ptr);


26:                 …


27:                 switch(cmd)


28:                 {


29:                 …


30:                 case BC_TRANSACTION: case BC_REPLY:


31:                     // 从用户空间得到binder_transaction_data数据


32:                     copy_from_user(&tr, ptr, sizeof(tr));


33:                     …


34:                     binder_transaction(proc, thread, tr=&tr,


35:                         reply=(cmd==BC_REPLY)=false)


36:                     {


37:                         …


38:                       if (reply) 


39:                         {    // 是回复


40:                …


41:                         }


42:                         else


43:                         {    // 是正向请求


44:                             if (tr->target.handle)


45:                             {    // 从红黑树中获得对应的节点


46:                                 ref = binder_get_ref(proc, tr->target.handle);


47:                                 …


48:                                 target_node = ref->node;


49:                             }


50:                             else…


51:                             // 找到节点对应的服务进程


52:                             target_proc = target_node->proc;


53:                             …


54:                         }


55:                         if (target_thread) …


56:                         else


57:                         {


58:                             target_list = &target_proc->todo;


59:                             target_wait = &target_proc->wait;


60:                         }


61:                         …


62:                         for(遍历其中的flat objects)


63:                         {


64:                             …在postBuffer这个例子中忽略


65:                             …在createSurface中它将消息内含flat object进行处理


66:                             … 以实现两侧物件BINDER和HANDLE类型转换,


67:                             … 即完成2.4的注释1中的过程:


68:                             switch(fp->type)


69:                             {


70:                             …


71:                             case BINDER_TYPE_BINDER:


72:                                 …


73:                                 node=binder_new_node(proc,


74:                                 ptr = fp->binder, cookie = fp->cookie)


75:                                 {


76:                                     …


77:                                     node->proc = proc;


78:                                     // 这个进程就是BnSurfaceFlingerClient和


79:                                     // BnSurface所在进程


80:                                     node->ptr = ptr;


81:                                     node->cookie = cookie;


82:                                     …


83:                                 }


84:


85:                                 …


86:                                 binder_get_ref_for_node(target_proc, node);


87:                                 …


88:                                 fp->type = BINDER_TYPE_HANDLE;


89:                                 …


90:                             }


91:                         }


92:                         …


93:                         // 激活点1:


94:                         // 唤醒进程(见“阻塞点2”)


95:                         // (对于在ServiceManager阶段会激活service_manager的“阻塞点1”)


96:                         wake_up_interruptible (target_wait);


97:                     }    // binder_transaction


98:                 }


99:             }    // binder_thread_write


100:             …


101:             binder_thread_read(…)


102:             {


103:                 … 读取数据


104:                 … 处理


105:                 if (t->buffer->target_node) {


106:


107:                     tr.target.ptr = target_node->ptr;


108:                     tr.cookie = target_node->cookie;    //本地对象指针


109:                     … 相应处理中会在ptr所指buffer中将cmd设置为


110:                     BR_TRANSACTION


111:                 }


112:             }


113:             if (读得数据)


114:                 wake_up_interruptible(&proc->wait); //激活等数据的用户进程


115:         }


116:         …


117:         // 反馈给用户空间


118:         copy_to_usr(ubuf, &bwr, sizeof(bwr));


119:     }


120: }


2.8 IPC处理和监听线程

以下Surface相关服务的进程入口(cmds/surfaceflinger/main_surfaceflinger.cpp):

1: int main(…)


2: {


3:     …


4:     SurfaceFlinger::instantiate()


5:   {    /* 实例化SurfaceFlinger服务 */


6:       sm = defaultServiceManager()


7:         {


8:             if (gDefaultServiceManager != NULL) return gDefaultServiceManager;


9:             …


10:             // 在当前进程中首次调用


11:


12:             co = ProcessState::self()->getContextObject(NULL)


13:             {


14:               if (supportsProcess()) {    /* Android支持此分支 */


15:                   return getStrongProxyForHandle(0)


16:                   {


17:                         具体流程类似2.4节介绍,生成一个新的BpBinder对象


18:                         (ServiceManager的实际对象作为Context,功能实体在启


19:                         动时已经产生,即2.3介绍的BServiceManager,所以此


20:                         处不在需要生成Bn对象)


21:                   }


22:                 } else …


23:             }


24:             gDefaultServiceManager = interaface_cast(co)


25:             {


26:                 …具体流程类似2.4节介绍,新建一个BpServiceManager对象


27:                   上述BpBinder对象作为其mRemote


28:             }


29:             return gDefaultServiceManager;


30:         }


31:         sm->addService()


32:         {


33:             远程调用,完成服务(SurfaceFlinger)的加载


34:         }


35:     }


36:


37:     …    其他服务创建 …


38:   ProcessState::self()->startThreadPool()


39:     {


40:         …


41:         spawnPoolThread(true)


42:         {


43:             创建线程运行IPCThreadState::self()->joinThreadPool(true)


44:         }


45:     }


46:


47:     IPCThreadState::self()->joinThreadPool()


48:     {


49:         …


50:         do {


51:             …处理输入信息


52:             talkWithDriver()


53:             {


54:                 通过ioctl和binder设备交换信息(见前几节介绍),


55:                 数据未到时挂起(阻塞点2)


56:             }


57:             …


58:             cmd = mIn.readInt32();


59:             executeCommand(cmd)


60:             {


61:                 switch(cmd)


62:                 {


63:                 …


64:                 case BR_TRANSACTION:


65:                     binder_transaction_data tr;


66:                     mIn.Read(&tr, sizeof(tr));


67:                     …


68:                     if (tr.target.ptr)


69:                     {


70:                         sp b = ((BBinder*)tr.cookie;    // 本地对象指针


71:                         b->transact(tr.code, buffer, &reply, 0)


72:                         {


73:                             BnSurface:: onTransact(…)


74:                             {


75:                                 switch(code)


76:                                 {


77:                                     …


78:                                     case POST_BUFFER:


79:                                         …


80:                                         offset = data.readInt32();


81:                                         postBuffer(offset);


82:                                     …


83:                                 }


84:                               …


85:                             }


86:                         }


87:                     }


88:                     …


89:                 }


90:             }


91:         } while (未完结);


92:          …


93:     }


94: }


以下是媒体相关服务进程入口:

1: int main(…)


2: {


3:     …


4:     MediaPlayerService::instantiate()    { 见上一段代码 }


5:   …    其他服务创建 …


6:   ProcessState::self()->startThreadPool() { 见上一段代码 }


7:     IPCThreadState::self()->joinThreadPool() { 见上一段代码 }


8: }


2.9 Surface总体流程

根据上述的Bp和Bn两侧生成过程原理分析SurfaceFlinger相关代码,可以发现:
通过ISurfaceFlinger::createConnection,两侧生成ISurfaceFlingerClient;
通过ISurfaceFlingerClient:: createSurface,两侧生成ISurface。
而服务SurfaceFlinger的Bp端最初通过获取服务取得,如下:

1: _get_surface_manager()


2: {


3:     if (gSurfaceManager != 0) return gSurfaceManager;


4:


5:   sm = defaultServiceManager() { 详见2.8节 }


6:


7:     …


8:     // 获得SurfaceFlinger服务(Bp侧句柄),其原理前面章节(如2.3节)


9:     binder = sm->getService(String16("SurfaceFlinger"));


10:     …


11:


12:     // 实际产生


13:     sp sc = interface_cast (binder)


14:   { 详见2.4节,sc实为BpSurfaceComposer }


15:


16:   if (gSurfaceManager == 0) gSurfaceManager = sc;


17:


18:     return gSurfaceManager;


19: }


加上前述Surface的分析,Surface的总体服务流程如图2所示,这些操作使得最终在客户应用中得到BpSurfaceComposer, BpSurfaceFlingerClient和BpSurface三个对象。而发起这些创建的是客户就是SurfaceFlingerClient,它在SurfaceSession(Java对象)中维护,可见SurfaceSession是创建Surface的关键对象。






2.10 MediaPlayerService服务总流程


1: android_media_MediaPlayer_setDataSource(…)    /* JNI */


2: {


3:     sp mp = getMediaPlayer(…)


4:   {


5:       获得Java对象中引用的MediaPlayer对象,


6:       它曾在android_media_MediaPlayer_native_setup中设置


7:         即一个新建的MediaPlayer对象。


8:         虽然它是BnMediaPlayer,但是接下来调用setDataSource将它绑定到一个远端


9:         的MediaPlayer上


10:     }


11:   MediaPlayer::setDataSource(url)


12:     {


13:         …


14:       sp &service = MediaPlayer::getMediaPlayerService()


15:       {


16:           sp sm = defaultServiceManager() {…}


17:           …


18:             binder = sm->getService("media.player") {…}


19:             …


20:             sMediaPlayerService = interface_cast(binder)


21:           { … 得到一个BpMediaPlayerService }


22:                     …


23:             return sMediaPlayerService;


24:         }


25:         …


26:             // 通过BpMediaPlayerService远程调用创建一个播放器


27:         sp player = service->create(…) {…}


28:         setDataSource(player)


29:         {


30:             … 


31:             mPlayer = player;    //  远端的实际功能播放器


32:             …


33:         }


34:         …


35:     }


36: }



参考资料:
http://hi.baidu.com/albertchen521/blog/item/30c32d3f4bee993a71cf6ca0.html
http://www.limodev.cn/blog/archives/777
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: