本文转自:http://blog.csdn.net/gzzaigcnforever/article/details/20606735

这篇博文其实就是想简单的来记录下Binder驱动在Android中的重要性,早在2012年的时候就按着2.3的源码深入学习过Binder驱动的底层实现(Android之binder驱动个人学习小结),Binder驱动主要是android为了构建C/S的通信模型而量身定做的,没有过多复杂的协议,一个Parcl基本包含了所要传递的所有信息,本文就对FrameWork从运用到的Binder机制做一个模型的总结。

还是先把Android的Binder驱动架构提炼出来先,如下图所示是典型的CS架构,和Binder驱动密切相关的结构体包括BBinder、BpBinder、BpRefBase:

论Android Binder驱动在Framework中的重要性_第1张图片

一个基于Binder的驱动架构,一般的实现过程分为如下几部:

先来看下Binder架构下涉及的一般类图布局会如下所示

论Android Binder驱动在Framework中的重要性_第2张图片

基于以上Android的类,我们构建的Ixxx定义整个通信的接口函数,主要由Bpxxx来实现但主要是进行命令字与数据的打包传输,然后远程链接到本地的Bnxxx进行业务的解析与处理。一般需要构建2个文件:Ixxx.h,Ixxx.cpp.

在Ixxx.h内部申请Ixxx接口类,以及类Bnxxx的申明,一般该类只对应一个成员函数即OnTransact;在Ixxx.cpp中主要实现类Bpxxx的申明以及对Ixxx的接口函数进行实现,其核心是调用BpBinder来实现的。

理解Binder最好的方式是ServiceManager,一般以BnxxxService命名服务,都会向其进行服务的注册,而BpxxxClient是直接通过和SM在客户端的代理来获取BnxxxService在本地的代理。

其实按照我个人的理解,Bpxxx和Bnxxx更好的理解是2个进程间的通信,当然作为Service和Client是最好的使用方式。比如先前通过一个客户端的BpxxxClient发出一个请求建立一个Client处的Bpxxx接口,相应的在服务端也就存在着Bnxxx的实现函数,故而这两者之间就可以实现正常的通讯,当然Bnxxx不在是以服务的形象存在与SM中,只是简单的实现进程、线程间的通信而已。

下面将从一个SurfaceFlinger进程的启动到Binder驱动的操作,以及Bnxxx和Bpxxx的通信来简单介绍。

step1:Binder驱动的open和mmap过程

[html] view plain copy
  1. intmain(intargc,char**argv){
  2. SurfaceFlinger::publishAndJoinThreadPool(true);
  3. //WhenSFislaunchedinitsownprocess,limitthenumberof
  4. //binderthreadsto4.
  5. ProcessState::self()->setThreadPoolMaxThreadCount(4);
  6. return0;
  7. }
[cpp] view plain copy
  1. sp<ProcessState>ProcessState::self()
  2. {
  3. Mutex::Autolock_l(gProcessMutex);
  4. if(gProcess!=NULL){
  5. returngProcess;
  6. }
  7. gProcess=newProcessState;
  8. returngProcess;
  9. }

ProcessState作为一个进程中唯一的变量(所谓的单列模式),他是真正和Binder驱动打交道的地方所在

[cpp] view plain copy
  1. ProcessState::ProcessState()
  2. :mDriverFD(open_driver())
  3. ,mVMStart(MAP_FAILED)
  4. ,mManagesContexts(false)
  5. ,mBinderContextCheckFunc(NULL)
  6. ,mBinderContextUserData(NULL)
  7. ,mThreadPoolStarted(false)
  8. ,mThreadPoolSeq(1)
  9. {
  10. if(mDriverFD>=0){
  11. //XXXIdeally,thereshouldbeaspecificdefineforwhetherwe
  12. //havemmap(orwhetherwecouldpossiblyhavethekernelmodule
  13. //availabla).
  14. #if!defined(HAVE_WIN32_IPC)
  15. //mmapthebinder,providingachunkofvirtualaddressspacetoreceivetransactions.
  16. mVMStart=mmap(0,BINDER_VM_SIZE,PROT_READ,MAP_PRIVATE|MAP_NORESERVE,mDriverFD,0);
  17. if(mVMStart==MAP_FAILED){
  18. //*sigh*
  19. ALOGE("Using/dev/binderfailed:unabletommaptransactionmemory.\n");
  20. close(mDriverFD);
  21. mDriverFD=-1;
  22. }
  23. #else
  24. mDriverFD=-1;
  25. #endif
  26. }
  27. LOG_ALWAYS_FATAL_IF(mDriverFD<0,"Binderdrivercouldnotbeopened.Terminating.");
  28. }

上述的构造函数主要完成Binder驱动的打开已经mmap的操作。

step2:Binder驱动的交互主要是接收其他的客户端请求

[cpp] view plain copy
  1. voidProcessState::startThreadPool()
  2. {
  3. AutoMutex_l(mLock);
  4. if(!mThreadPoolStarted){
  5. mThreadPoolStarted=true;
  6. spawnPooledThread(true);
  7. }
  8. }
[cpp] view plain copy
  1. voidIPCThreadState::joinThreadPool(boolisMain)
  2. {
  3. talkWithDriver();
  4. executeCommand();
  5. }

在这里是通过获取和binder驱动的交互,得到待处理的信息后进行executeCommand的执行,该函数其实内部就是找到对应的本地的BBinder来执行他的transact,而通过上图的继承关系可知,一般就直接有Bnxxx的Ontransact来解析完成,如下所示;

[cpp] view plain copy
  1. status_tBBinder::transact(
  2. uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
  3. {
  4. data.setDataPosition(0);
  5. status_terr=NO_ERROR;
  6. switch(code){
  7. casePING_TRANSACTION:
  8. reply->writeInt32(pingBinder());
  9. break;
  10. default:
  11. err=onTransact(code,data,reply,flags);//虚函数子类被重载break;
  12. }
  13. if(reply!=NULL){
  14. reply->setDataPosition(0);
  15. }
  16. returnerr;
  17. }


step3: 作为客户端是如何发送相关消息的

当你在Client有了对应的proxy后,直接操作的就是BpBinder的相关内容,我们常常见到的remote->(xxx)其实内部的实现是这样的:

[cpp] view plain copy
  1. status_tBpBinder::transact(
  2. uint32_tcode,constParcel&data,Parcel*reply,uint32_tflags)
  3. {
  4. //Onceabinderhasdied,itwillnevercomebacktolife.
  5. if(mAlive){
  6. status_tstatus=IPCThreadState::self()->transact(
  7. mHandle,code,data,reply,flags);
  8. if(status==DEAD_OBJECT)mAlive=0;
  9. returnstatus;
  10. }
  11. returnDEAD_OBJECT;
  12. }

可以看到是一个IPCThreadState在和帮助者你,再看他的transaction:

[cpp] view plain copy
  1. status_tIPCThreadState::transact(int32_thandle,
  2. uint32_tcode,constParcel&data,
  3. Parcel*reply,uint32_tflags)//数据的发送
  4. {
  5. if(reply){
  6. err=waitForResponse(reply);//等待服务端的回复
  7. }
[cpp] view plain copy
  1. status_tIPCThreadState::waitForResponse(Parcel*reply,status_t*acquireResult)
  2. {
  3. status_tIPCThreadState::talkWithDriver(booldoReceive)//和底层走的最近的地方
  4. }



其实无论是Binder的服务端还是客户端,真正的Binder在内核驱动中度会为当前的进程维护一个binder的node树,只有有新的节点产生经过内核驱动后都会记录下来,使得一旦远程的客户通过代理访问时,都是能找到对应的Binder实体,并找个该实体所示的loop服务线程,进行必要的唤醒与处理。最终反馈处理后的数据到客户端,客户端益是从线程的等待到唤醒这个过程来响应相关的处理结果,进行保存。

Binder驱动在下面要介绍的camera和SurfaceFlinger架构中会普遍的用到,所以先在这里总一个最简单的应用方式总结,以便更好的阅读代码。


更多相关文章

  1. H5做的商城客户端,效果很不错
  2. Android原生代码调用H5 Web网页中的Javascript函数方法
  3. Android架构模式之AAC
  4. android下的MVP架构
  5. Android项目--团购类客户端

随机推荐

  1. Android(安卓)最佳实践
  2. android 基本概念和一些术语
  3. 利用Handler来更新android的UI (2)
  4. Android开发环境搭建
  5. android 显示特殊符号
  6. Android多媒体开发高级编程
  7. Android(安卓)开发最佳实践
  8. AndroidStudio 3.0 加载Android(安卓)sup
  9. ProgressBar的简单使用
  10. android防止屏幕关闭后后台服务停止运行