2019独角兽企业重金招聘Python工程师标准>>>

上文《Android系统的Binder机制之一——Service Manager》我们学习了Service Manager在Android Binder中的作用——服务(Service)注册,服务(Service)查询的功能。本文我们一起学习服务(Service)在客户端中的代理机制。重点介绍其核心对象BpBinder。

1、服务代理的原理

如下是客户端请求service服务的场景:

1、首先客户端向Service manager查找相应的Service。上文《Android系统的Binder机制之一——Service Manager》有比较详细的介绍。注意客户端和Service可能在两个不同的进程中。 
2、Android系统将会为客户端进程中创建一个Service代理。下文将详细介绍该创建过程。 
3、客户端视角只有Service代理,他所有对Service的请求都发往Service代理,然后有Service代理把用户请求转发给Service本身。Service处理完成之后,把结果返回给Service代理,Service代理负责把处理结果返回给客户端。注意客户端对Service代理的调用都是同步调用(调用挂住,直到调用返回为止),这样客户端视角来看调用远端Service的服务和调用本地的函数没有任何区别。这也是Binder机制的一个特点。

2、Android进程环境——ProcessState类型和对象

在Android系统中任进程何,要想使用Binder机制,必须要创建一个ProcessState对象和IPCThreadState对象。当然如果Android进程不使用Binder机制,那么这两个对象是不用创建的。这种情况很少见,因为Binder机制是整个Android框架的基础,可以说影响到Android方方面面。所以说了解这两个对象的作用非常重要。

台湾的高焕堂先生一片文章《认识ProcessState类型和对象》,可以在我的博文《(转)高焕堂——Android框架底层结构知多少?》中找到。可以先通过这篇文章对ProcessState进行一个大概了解。

ProcessState是一个singleton类型,一个进程只能创建一个他的对象。他的作用是维护当前进程中所有Service代理(BpBinder对象)。一个客户端进程可能需要多个Service的服务,这样可能会创建多个Service代理(BpBinder对象),客户端进程中的ProcessState对象将会负责维护这些Service代理。

我们研究一下创建一个Service代理的代码:

   1: sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
   2: {
   3:     sp<IBinder> result;
   4: 
   5:     AutoMutex _l(mLock);
   6: 
   7:     handle_entry* e = lookupHandleLocked(handle);
   8: 
   9:     if (e != NULL) {
  10:         // We need to create a new BpBinder if there isn't currently one, OR we
  11:         // are unable to acquire a weak reference on this current one.  See comment
  12:         // in getWeakProxyForHandle() for more info about this.
  13:         IBinder* b = e->binder;
  14:         if (b == NULL || !e->refs->attemptIncWeak(this)) {
  15:             b = new BpBinder(handle);
  16:             e->binder = b;
  17:             if (b) e->refs = b->getWeakRefs();
  18:             result = b;
  19:         } else {
  20:             // This little bit of nastyness is to allow us to add a primary
  21:             // reference to the remote proxy when this team doesn't have one
  22:             // but another team is sending the handle to us.
  23:             result.force_set(b);
  24:             e->refs->decWeak(this);
  25:         }
  26:     }
  27: 
  28:     return result;
  29: }

    getWeakProxyForHandle函数的作用是根据一个binder句柄(上文《 Android系统的Binder机制之一——Service Manager 》提到Binder驱动为每个Service维护一个Binder句柄,客户端可以通过句柄来和Service通讯)创建对应的Service代理对象。

当前进程首先调用lookupHandleLocked函数去查看当前进程维护的Service代理对象的列表,该待创建Service代理对象是否已经在当前进程中创建,如果已经创建过了,则直接返回其引用就可以了。否则将会在Service代理对象的列表增加相应的位置(注意系统为了减少分配开销,可能会多分配一些空间,策略是“以空间换时间”),保存将要创建的代理对象。具体代码请参考lookupHandleLocked的源码。

后面代码就好理解了,如果Service代理对象已经创建过了,直接增加引用计数就行了。若没有创建过,则需要创建一个新的Service代理对象。

3、Android进程环境——IPCThreadState类型和对象

Android进程中可以创建一个ProcessState对象,该对象创建过程中会打开/dev/binder设备,并保存其句柄。并初始化该设备。代码如下:

   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:         // XXX Ideally, there should be a specific define for whether we
  12:         // have mmap (or whether we could possibly have the kernel module
  13:         // availabla).
  14: #if !defined(HAVE_WIN32_IPC)
  15:         // mmap the binder, providing a chunk of virtual address space to receive transactions.
  16:         mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
  17:         if (mVMStart == MAP_FAILED) {
  18:             // *sigh*
  19:             LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
  20:             close(mDriverFD);
  21:             mDriverFD = -1;
  22:         }
  23: #else
  24:         mDriverFD = -1;
  25: #endif
  26:     }
  27:     if (mDriverFD < 0) {
  28:         // Need to run without the driver, starting our own thread pool.
  29:     }
  30: }

    mDriverFD保存了/dev/binder设备的句柄,如果仔细查看ProcessState的源码会发现这个句柄不会被ProcessState对象使用。那么保存这个句柄做什么用呢?被谁使用呢?非常奇怪。经过查看ProcessState的头文件,发现如下代码:
   1: friend class IPCThreadState;

    发现IPCThreadState是ProcessState的友元类,那么就可以怀疑这个句柄是被IPCThreadState的对象使用的,然后查看代码发现确实如此。

IPCThreadState也是一个singleton的类型,一个进程中也只能有一个这样的对象。我们查看一下它的talkWithDriver函数:

   1: ...........
   2: if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
   3:     err = NO_ERROR;
   4: else
   5:     err = -errno;
   6: ...........

    IPCThreadState通过ioctl系统调用对ProcessState打开的句柄进行读写。这样我们也可以看出IPCThreadState对象的作用:
1、维护当前进程中所有对/dev/binder的读写。换句话说当前进程通过binder机制进行跨进程调用都是通过IPCThreadState对象来完成的。

2、 IPCThreadState也可以理解成/dev/binder设备的封装,用户可以不直接通过ioctl来操作binder设备,都通过IPCThreadState对象来代理即可。

     我们这里可以再深入地聊一下,不管是客户端进程和Service进程都是需要用IPCThreadState来和binder设备通讯的。如果是客户端进程则通过服务代理BpBinder对象,调用transact函数,该函数作用就是把客户端的请求写入binder设备另一端的Service进程,具体请参阅IPCThreadState类的transact方法。作为Service进程,当他完成初始化工作之后,他需要他们需要进入循环状态等待客户端的请求,Service进程调用它的IPCThreadState对象的joinThreadPool方法,开始轮询binder设备,等待客户端请求的到来,后面我们讨论Service时候会进一步讨论joinThreadPool方法。有兴趣的朋友可以先通过查看代码来了解joinThreadPool方法。

4、Service代理对象BpBinder

    上文关于ProcessState的介绍提到了,客户端进程创建的Service代理对象其实就是BpBinder对象。
    我们首先了解怎样创建BpBinder对象。
   1: BpBinder::BpBinder(int32_t handle)
   2:     : mHandle(handle)
   3:     , mAlive(1)
   4:     , mObitsSent(0)
   5:     , mObituaries(NULL)
   6: {
   7:     LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
   8: 
   9:     extendObjectLifetime(OBJECT_LIFETIME_WEAK);
  10:     IPCThreadState::self()->incWeakHandle(handle);
  11: }

    我们可以看出首先是通过IPCThreadState读写binder设备增加中相应binder句柄上的Service的引用计数。然后本地保存代理Service的binder句柄mHandle。

客户进程对Service的请求都通过调用BpBinder的transact方法来完成:

   1: status_t BpBinder::transact(
   2:     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
   3: {
   4:     // Once a binder has died, it will never come back to life.
   5:     if (mAlive) {
   6:         status_t status = IPCThreadState::self()->transact(
   7:             mHandle, code, data, reply, flags);
   8:         if (status == DEAD_OBJECT) mAlive = 0;
   9:         return status;
  10:     }
  11: 
  12:     return DEAD_OBJECT;
  13: }

在transact方法中,还是调用客户进程的IPCThreadState对象来完成对相应Service请求。注意transact方法是同步方法,将会挂住客户进程的当前线程,直到service把请求处理完成,并返回结果。这时客户进程当前线程的transact方法返回。

5、Android系统对Binder机制的抽象——IBinder

上面我们讲解了Binder机制比较底层的机制,这些机制直接用还是比较麻烦的,比如使用binder设备的ioctl,需要记住很多ioctl的代码。

Android为了是Binder机制容易使用,对Binder机制进行了抽象,定义了IBinder接口,该接口在C/C++和Java层都有定义。IBinder定义了一套使用Binder机制使用和实现客户程序和服务器的通讯协议。可以理解如下定义:

1、向Android注册的Service也必须是IBinder(继承扩展IBinder接口)对象。后续文章中我们讨论Service的时候我们会介绍到这方面的内容。

2、客户端得到Service代理对象也必须定义成IBinder(继承扩展IBinder接口)对象。这也是为什么BpBinder就是继承自IBinder。

3、客户端发送请求给客户端,调用接口的Service代理对象IBinder接口的transact方法。

4、Android系统Binder机制将负责把用户的请求,调用Service对象IBinder接口的onTransact方法。具体实现我们将在以后介绍Service的时候讨论。

6、Service Manager代理对象

我们知道Service Manager是Android Binder机制的大管家。所有需要通过Binder通讯的进程都需要先获得Service Manager的代理对象才能进行Binder通讯。Service Manager即在C/C++层面提供服务代理,又在Java层面提供服务代理,本文先介绍一下C/C++层面的服务代理,Java层面的服务代理将在后续文章中介绍。

进程在C/C++层面上面,Android在Android命名空间中定义了一个全局的函数defaultServiceManager(定义在framework/base/libs/binder),通过这个函数可以使进程在C/C++层面获得Service Manager的代理。我们先看一下该函数的定义:

   1: sp<IServiceManager> defaultServiceManager()
   2: {
   3:     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
   4:
   5:     {
   6:         AutoMutex _l(gDefaultServiceManagerLock);
   7:         if (gDefaultServiceManager == NULL) {
   8:             gDefaultServiceManager = interface_cast<IServiceManager>(
   9:                 ProcessState::self()->getContextObject(NULL));
  10:         }
  11:     }
  12:
  13:     return gDefaultServiceManager;
  14: }

我们可以看到defaultServiceManager是调用ProcessState对象的getContextObject方法获得Service Manager的getContextObject方法获得Service Manager代理对象。我们再看一下getContextObject函数的定义:

   1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
   2: {
   3:     if (supportsProcesses()) {
   4:         return getStrongProxyForHandle(0);
   5:     } else {
   6:         return getContextObject(String16("default"), caller);
   7:     }
   8: }

我们可以看出其实是调用我们上面描述过的getStrongProxyForHandle方法,并以句柄0为参数来获得Service Manager的代理对象。

ProcessState::self()->getContextObject(NULL)返回一个IBinder对象,怎样把它转化成一个IServiceManager的对象呢?这就是模板函数interface_cast<IServiceManager>的作用了。调用的是IServiceManager.asInterface方法。IServiceManager的asInterface方法通过DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE宏来定义,详细情况请查看IServiceManager类的定义。IMPLEMENT_META_INTERFACE宏关于asInterface的定义如下:

   1: android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
   2:         const android::sp<android::IBinder>& obj)                   \
   3: {                                                                   \
   4:     android::sp<I##INTERFACE> intr;                                 \
   5:     if (obj != NULL) {                                              \
   6:         intr = static_cast<I##INTERFACE*>(                          \
   7:             obj->queryLocalInterface(                               \
   8:                     I##INTERFACE::descriptor).get());               \
   9:         if (intr == NULL) {                                         \
  10:             intr = new Bp##INTERFACE(obj);                          \
  11:         }                                                           \
  12:     }                                                               \
  13:     return intr;                                                    \
  14: }                                                                   \

最终asInterface将会用一个IBinder对象创建一个BpServiceManager对象,并且BpServiceManager继承自IServiceManager,这样我们就把IBinder对象转换成了IServiceManager对象。如果你仔细查看BpServiceManager的定义,你会发现查询Service,增加Service等方法其实都是调用底层的IBinder对象来完成的。

当我们在C/C++层面编写程序使用Binder机制的时候将会调用defaultServiceManager函数来获得Service Manager,比如:很多Android系统Service都是在C/C++层面实现的,他们就需要向Service Manager注册其服务,那么这些服务将调用defaultServiceManager获得Service Manager代理对象。我们在后续介绍Android系统Service的时候将会详细介绍。

7、总结

本文中我们介绍了C++层面的Service代理,后续文章我们将介绍Java层面的Service代理。

转载于:https://my.oschina.net/kangchunhui/blog/70806

Android系统的Binder机制之二——服务代理对象(1)相关推荐

  1. binder 从c到java_Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析...

    在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的源代码.细心的读者会发现,这几篇文章分析的Binder接口都是 ...

  2. Android深入浅出之Binder机制

    Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白B ...

  3. [Innost]Android深入浅出之Binder机制

    ZZ FROM:http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html ============================== ...

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

    Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白B ...

  5. android深入浅出binder机制,Android深入浅出之Binder机制.pdf

    Android深入浅出之Binder机制 Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Bind ...

  6. (zz)Android深入浅出之Binder机制

    Android深入浅出之Binder机制 原文地址:http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html 一 说明 Android ...

  7. 深入理解Android音视频同步机制(二)ExoPlayer的avsync逻辑

    深入理解Android音视频同步机制(一)概述 深入理解Android音视频同步机制(二)ExoPlayer的avsync逻辑 深入理解Android音视频同步机制(三)NuPlayer的avsync ...

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

    为什么在Android中使用binder通信机制? 众所周知linux中的进程通信有很多种方式,比如说管道.消息队列.socket机制等.socket我们再熟悉不过了,然而其作为一款通用的接口,通信开 ...

  9. Android Binder机制(二) ------- 服务的实现

    服务分析 所谓服务,简单点就是不断的监听客户端的请求,然后处理并向客户端返回处理的结果.要实现这一功能,至少需要以下几点: 循环,我们的服务就是一个大循环,不断的监听客户发来的请求.(线程循环) 通讯 ...

  10. 理解Android系统的进程间通信原理(二)----RPC机制

    理解Android系统中的轻量级解决方案RPC的原理,需要先回顾一下JAVA中的RMI(Remote Method Invocation)这个易于使用的纯JAVA方案(用来实现分布式应用).有关RMI ...

最新文章

  1. 深度学习框架Caffe2并入PyTorch,你的开发效率可能要提升不少
  2. n2n linux,n2n安装
  3. ufs 固态硬盘_NVMe SSD新利器?WTG最高级别评分 阿卡西斯NVMe M.2移动固态硬盘盒评测...
  4. C++ 十大经典排序算法原理及模板之STL方法实现以及稳定性分析
  5. 很少有人能把CDN说的这么有趣了
  6. 如何利用python在一个wen'dang'li_如何利用Python网络爬虫给自己跟朋友来一份穷游攻略!走到哪里穷到哪里的哦!...
  7. Java 判断是否包含指定的子串 contains()
  8. 解析Cloudera Manager内部结构、功能包括配置文件、目录位置等
  9. 演示:各种网络安全设备、***设备向微软证书服务器申请证书
  10. python3 os.system 异步执行_《sentos python教程》 Python os.system(command),这样执行的command命令,和主程序是异步的吗?...
  11. 使用SQL Server发布数据库快照遇到错误:对路径”xxxxx“访问被拒绝的解决方法...
  12. 网络协议:传输层(http://java-mzd.iteye.com/blog/1007577)
  13. win10 Abaqus2018 血泪备注
  14. 双闭环可逆直流脉宽pwm调速系统设计及matlab仿真验证_,双闭环可逆直流脉宽PWM调速系统的设计最终版(手机版)...
  15. html中给div加链接,用html给div加类似a标签的超链接(转)
  16. 最新Flutter 微信分享功能实现
  17. 手机上的环境光传感器
  18. The Innovation | Volume 3 Issue 3 Live Now
  19. android 展示pdf文件
  20. PPT最强抠图技巧(收藏必备)

热门文章

  1. RGB图像转到HSI图像
  2. 利用composer搭建PHP框架(四.数据库与缓存)
  3. 计算机三位科学家,华南理工大学这三位年轻科学家太优秀了!
  4. 实习踩坑之路:利用Java8新特性实现不同范型List之间的相互转换
  5. 设计模式-04-行为型模式详解
  6. JavaSE学习--集合01
  7. JavaEE学习01--Tomcat服务器
  8. Android RootTrustManager 证书校验简单分析
  9. Activity的Launch mode详解 singleTask正解
  10. ajax 请求与响应,实例解读ajax发送请求与数据响应