android分析之Binder 01

终于还是得写一篇关于Binder的文章了。从最初接触Android到花大把时间研究Android源码,Binder一直是分析道路的拦路虎。看了几本最流行的Android源码分析书籍,每次基本上都不能把Binder相关知识看完、读透。好在一直没有放弃,第一次理解不了就跳过,下一次重新读,每次读都有新的收获。现在是时候整理整理了。

  我理解的Binder是什么?一种IPC(跨进程通信)的实现方式。注意“跨进程”,表明数据从一个进程“流向”了另一个进程。首先要了解为什么跨进程那么难?因为应用程序的地址空间都是虚地址,通过映射到物理内存空间。假如应用程序都直接在物理内存空间操作,那应用程序跨进程就非常方便了,直接传递物理地址就好了。但是,不同应用程序使用的是通过内存管理器作映射的虚拟内存空间,至于映射到哪个物理内存区域,这是未知的,从而使得跨进程传递数据变得不那么方便,但也不是没有办法。Linux中典型的管道、消息队列、共享内存等都可以实现跨进程通信。Android采用了Binder方式,自然有它的优势,所谓“灵活、方便”,这个优势还在慢慢体会中。

  要深刻理解android的Binder机制,有几点是需要理解的:

  1. android操作系统内部,可以看成一种基于C/S架构的服务提供机制。由Client发出某种服务请求,由Service执行服务并返回结果。比如一个APP需要使用照相机就需要向MediaService提出服务请求,而这两个进程之间的通信,就是通过Binder来完成,android中存在大量的这种C/S结构。
  2. 进程与类的区别:一个进程可以提供多种服务(可以通过多线程的方式,也可以是逻辑判断提供哪种服务),比如MediaService是android中的一个进程,提供了AudioFlinger服务、AudioPolicyService服务、MediaPlayerService服务等。在分析的过程中,要时刻明白当前进程执行的代码是什么。
  3. 通信与业务要区分开来:Binder说到底是一种通信方式,那么谁使用它呢?那肯定是上层代码。这里说是“上层代码”,是因为代码框架的层次结构是分析重点。这些上层代码可能在不同进程中执行。

如果看过Service实现,或者各种类的继承关系,它们是有一定的层次关系的。现在采用“从下往上”的逐层分析,在看源码时,个人发现“从下往上”往往可以取得就好的效果。结合《深入理解android 卷1》第六章来分析。

  • Binder是一个“设备”

  有设备就离不开设备驱动,Binder实际上就是一个包含驱动、协议的伪设备,通过常用的对设备的操作,如open、ioctl、mmap等,可以操作Binder这个“设备”。其中关键点为:通过mmap可以把一块虚拟地址与物理地址映射起来,这时候,A进程与Binder共享同一块物理内存,如果另一个B进程也通过Binder共享了这块内存,那么A、B两进程就共享了同一块内存——这就是不同应用程序共享内存的(通过Binder)的原理。还有有一句话就是,如果到这里,两个进程之间已经完全可以通过这个Binder来通信了,当然实现细节肯定很麻烦。故要做封装!!根据上面所说的第3点,这里仍然在描述通信细节,还没有涉及到业务。Binder驱动本身比较复杂,不作分析。可以简单化它:通过它可以作内存共享即可——打开Binder设备、执行mmap、通过Binder驱动发送请求、获取结果。

  • ProcessState和IPCThreadState

  既然要做封装,那么这一层应该是封装对Binder设备的操作细节,分析代码也的确是这样。从抽象的角度来说,封装肯定是为了更简便的操作,如果把Binder的打开、执行mmap等等结果封装好,那上层只需要调用相应的接口就好了,达到封装的目的。

  首先得明白,ProcessState和IPCThreadState是两个类,好像是废话,但它俩的名字起得让人“浮想联翩”,老是让我把它们当做进程、线程。我们知道,一个应用程序对应一个Linux进程,OK,知道这个就好了,更多可访问:http://blog.csdn.net/mirkerson/article/details/38128637 。ProcessState和IPCThreadState就是为了进程/线程执行Binder更加方便而作的封装。

ProcessState::ProcessState()
    : mDriverFD(open_driver())//打开Binder以及对Binder的相关映射操作,不细看
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // XXX Ideally, there should be a specific define for whether we
        // have mmap (or whether we could possibly have the kernel module
        // availabla).
#if !defined(HAVE_WIN32_IPC)
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
        }
#else
        mDriverFD = -1;
#endif
    }

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

  通过上面的分析可知,对Binder的封装果然是在ProcessState里完成,实际上是使用IPCThreadState来完成——这里直接给出结果:每个进程有一个ProcessState实例,每个线程有一个IPCThreadState实例,具体的通信由每个线程自己与Binder完成,(因为采用了单例模式)。

  • IBinder、BpBinder和BBinder

  刚才看到了ProcessState对Binder的封装,可是这个封装还不够。因为ProcessState只是对Binder的打开、mmap等作了封装,具体数据应该怎么传入Binder,传入什么样的数据等还需要更细粒度的封装,这就是IBinder。IBinder提供了子类BpBinder和BBinder的通用部分,BpBinder和BBinder就用这个通用部分来通信。到目前为止,还是在分析通信行为,没有涉及业务。

查看BpBinder的transact实现:

status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Once a binder has died, it will never come back to life.
    if (mAlive) {
        status_t status = IPCThreadState::self()->transact(//的确是调用了IPCThreadState来与Binder通信
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}

  为了不复杂化,到这里只需要知道IBinder作为基类,“制定”了Client和Server端的通信的接口,具体由BpBinder和BBinder来实现。

  • 业务层

  面向对象中一个重要的继承,就是为了将通用部分单独成为一个类(抽象类、接口),然后继承,这样子类都有基类的变量或者方法。业务层也是这个逻辑,Client和Server两端分别实现通用部分(假如是接口),再按照接口中的方法分别实现自己的逻辑,这样就简洁多了。以MediaService为例,它的通用部分是IServiceManager,Client端为BpServiceManager,Server端为BnServiceManager。一直不明白,BpServiceManager和BnServiceManager在不同进程中执行,为什么一定要设计成具有IServiceManager这样一个基类呢?其实,如果没有基类,通信也完全可以的,只不过需要更多、更复杂一点的数据来保证,对方能够明白我想要的执行动作是什么。

走到这里,通信层,业务层都已经说明完了。小结:

  1. 类名中带有“Binder”的类是为了通信而实现的
  2. 业务层利用通信层实施通信
  • 通信层与业务层的粘合

从上图中可以看到,实际上的类继承关系比上面论述的稍微复杂一点。这里把我两个关键点就可以把不同层给粘合在一起:

  1. BnServiceManager直接继承了BBinder,表示BnServiceManager可以直接参与Binder通信。
  2. BpServiceManager所继承的BpRefBase有一个mRemote的IBinder类型变量,在实际代码中会指向BpBinder,这样BpServiceManager就可以通过BpBinder来与BBinder通信了。

到这里,就把Binder通信的框架分析完毕。

总结来说:将通信与业务层分离,专注实现各自逻辑,并恰当的粘合在一起,成为一个完整的基于Binder的跨进程通信。

时间: 2024-08-10 01:58:22

android分析之Binder 01的相关文章

android分析之Binder 02

分析Java层的ServiceManager,看看Binder在Java层是如何实现的. public final class ServiceManager { private static final String TAG = "ServiceManager"; private static IServiceManager sServiceManager;//IserviceManager是一个接口,定义了通用(公共)方法. private static HashMap<Str

Android Native层Binder.transact()函数调用 Binder.onTransact() 函数失败分析

Q:Android Native层Binder.transact()函数调用 Binder.onTransact() 函数失败? 在Android Native层调用Camera.h中的api实现一个截屏功能的应用时,发现通过gCamera->setListener(new ScreenCaptureListener())设置到Camera的mListener的用于接收Camera预览数据的回调函数没有被调用,导致截屏失败? 注: Camera类文件汇总: libcamera_client.so

从源码角度分析Android中的Binder机制的前因后果

前面我也讲述过一篇文章<带你从零学习linux下的socket编程>,主要是从进程通信的角度开篇然后延伸到linux中的socket的开发.本篇文章依然是从进程通信的角度去分析下Android中的进程通信机制. 为什么在Android中使用binder通信机制? 众所周知linux中的进程通信有很多种方式,比如说管道.消息队列.socket机制等.socket我们再熟悉不过了,然而其作为一款通用的接口,通信开销大,数据传输效率低,主要用在跨网络间的进程间通信以及在本地的低速通信.消息队列和管道

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的 源代码.细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我 们如何使用Java语言来使用系统的Binder机

Android内核之Binder

一,Binder框架讲解Binder是一种框架,这种架构提供了服务端接口,Binder驱动,客户端接口三个模块服务端 一个Binder服务端实际上就是一个Binder类对象,该对象那个一旦创建,内部就会创建一个隐藏的线程,该线程就会接收Binder驱动发送的消息,收到消息后,会执行Binder中的onTransact()函数,并按照该函数的参数执行不同的服务代码,因此 ,要是先一个onTransact()方法Binder驱动Binder驱动,任意一个服务端Binder对象被创建时,同时会在Bin

Android深入浅出之Binder机制(转)

Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白Binder的话,在很大程度上就能理解程序运行的流程. 我们这里将以MediaService的例子来分析Binder的使用: l         ServiceManager,这是Android OS的整个服务的管理程序 l         MediaService,这个程序里边注册了提供媒体播放的服

初识Android进程间通信之----Binder机制

[转载请注明出处:http://blog.csdn.net/feiduclear_up/article/details/51405967 CSDN废墟的树] 前言 前面两篇博客分别介绍了Android进程间通信之AIDL的使用,以及使用AIDL传递复杂对象以及Bitmap对象.所谓AIDL:Android Interface Definition Language,是一种Android接口定义语言,用于编写Android进程间通信代码.也就是说AIDL只是一个实现进程间通信的一个工具,真正实现A

Android深入浅出之Binder机制【转】

Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白Binder的话,在很大程度上就能理解程序运行的流程. 我们这里将以MediaService的例子来分析Binder的使用: <!--[if !supportLists]-->l         <!--[endif]-->ServiceManager,这是Android OS的整个服务

Android IPC机制—Binder的工作机制

进程和线程的关系 IPC机制即为跨进程通信,是inter-Process Communication的缩写.是指两个进程之间进行通信.在说进程通信之前,我们的弄明白什么是线程,什么是进程.进程和线程是两个截然不同的概念.按照操作系统中的描述,线程是CPU调度的最小单位,同时线程也是一种有限的系统资源.而进程一般是指一个执行单元,在pc端或者移动端上是指一个程序或者一个应用.一个进程中可以包含一个或者是多个线程.所以他们的关系应该是包含和被包含的关系. 跨进程的种类 在Android中跨进程通信的