Android-深入理解Binder

Posted 天津 唐秙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android-深入理解Binder相关的知识,希望对你有一定的参考价值。

文章目录

深入理解Binder

1. 概述

  Binder是android系统提供的一种IPC机制(进程间通信),由于Android是基于Linux内核的,因此除了Binder以外,还存在其他的IPC机制,如管道和Socket等。Android系统基本上可以看作是一个基于Binder通信的C/S架构,Binder就像是网络一样,把系统的各个部分连接在了一起,因此它是非常重要的。
在Binder通信的C/S架构体系中,除了C/S架构所包括的Client端和Server端外,Android还有一个全局的ServiceManager端,它的作用是管理系统中的各种服务。

  1.一个Server进程可以注册多个Service。
  2.Server进程要先注册一些Service到ServiceManager中,所以Server是ServiceManager的客户端,而ServiceManager就是服务端。
  3.如果某个Client进程要使用某个Service,必须先到ServiceManager中获取该Service的相关信息,所以Client是ServiceManager的客户端
  4.Client根据得到的Service信息与Service所在的Server进程建立通信的通路,然后就可以直接与Service交互了,所以Client也是Server的客户端。
  5.三者的交互都是基于Binder通信的,所以通过任意两者之间的关系,都可以揭示Binder的奥秘。

  Binder通信与C/S架构之间的关系,Binder只是为C/S架构提供了一种通信的方式,我们完全可以采用其他IPC方式进行通信,例如中有很多其他的程序就是采用Socker或者Pipe方式进行进程间通信的。

2. 解析MediaServer

  MediaServer简称MS,是一个用C++编写的可执行程序,因为这个Server是系统诸多重要Service的栖息地:
  1.AudioFlinger:音频系统中的核心服务
  2.AudioPolicyService:音频系统中关于音频策略的重要服务
  3.MediaPlayerService:多媒体系统中的重要服务
  4.CameraService:有关摄像/照相的重要服务

2.1 MediaServer的入口函数

  MS是一个可执行程序,入口函数是main,代码如下:

2.2 ProcessState

  我们在main函数的开始就遇到了ProcessState,由于每一个进程只有一个ProcessState,所以他是独一无二的,调用方式如下:

1.单例的ProcessState

  self函数采用了单例模式,每个进程只有一个ProcessState对象

2.ProcessState的构造
  ProcessState的构造函数打开了Binder设备

3.打开binder设备
  open_driver的作用就是打开/dev/binder这个设备,它是Android在内核中为完成进程间通信而专门设置的一个虚拟设备,实现如下:

Process::self函数就分析完了,总结如下:
  1.打开/dev/binder设备,这就相当于与内核的Binder驱动有了交互的通道
  2.对返回的fd使用mmap,这样Binder驱动就会分配一块内存来接受数据
  3.由于ProcessState具有唯一性,因此一个进程只会打开设备一次

2.3 defaultServiceManager

  1.defaultServiceManager函数的实现在IServiceManager.cpp中完成,它会返回一个IServiceManager对象,通过这个对象,我们可以同另一个进程ServiceManager进行交互。

  调用了ProcessState的getContextObject函数,这里传给它的参数是NULL,代码如下:

  getStrongProxyForHandle调用参数名叫做handle,在Windows编程中经常使用这个名称,是对资源的一种标识,其实就是有一个资源项,保存在一个资源数组,handle的值正是该资源项在数组中的索引。

2.BpBinder
  BpBinder和BBinder都是Android中与Binder通信相关的代表,都是从IBinder类中派生出来的。

  1.BpBinder是客户端用来与Server交互的代理类,p即Proxy代理的意思。
  2.BBinder则是与proxy相对的一端,它是proxy交互的目的端,如果Proxy代表客户端,那么BBinder则代表服务器,这里的BpBinder和BBinder是一一对应的,即某个BpBinder只能和对应的BBinder交互,我们也不希望BpBinderA发送的请求,却由BBinderB来处理。

  刚才我们在defaultService Manager()函数中创建了这个BpBinder。
问题一:为什么创建的不是BBinder?
  因为我们是ServiceManager的客户端,当然得使用代理端与ServiceManager进行交互
问题二:BpBinder和BBinder是一一对应的,那么BpBinder如何标识它对应的BBinder端呢?
  答案是Binder系统通过handler来标识相应的BBinder,我们给BpBinder构造函数传的参数handle的值是0,这个0在整个Binder系统中有重要含义,因为0
代表的就是ServiceManger所对应的BBinder。

BpBinder代码如下:


  这里的interface_cast其实是一个障眼法

3.interface_cast
  interface_cast,dynamic_cast和static_cast看起来是否非常眼熟?它们是指针类型转换的意思吗?如果是,那又是如何将BpBinder类型强制转化为IServiceManager类型呢?
interface_cast的具体实现:

4.IServiceManager
  IServiceManager定义了ServiceManager所提供的服务

  Android巧妙的通过DECLARE_META_INTERFACE和IMPLENT宏,将业务和通信挂钩,DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE这两个宏都定义在刚才的IInterface.h中:

  将IServiceManager的DELCARE宏进行相应的替换后得到的代码如下所示:




  interface_cast是如何吧BpBinder指针转换成一个IServiceManager指针的?

intr = new BpServiceManager(obj);

  interface_cast不是指针的转换,而是利用BpBinder对象作为参数新建一个BpServiceManager对象。

IServiceManager家族

  1.IServiceManager、BpServiceManager和BnServiceManger都与业务逻辑相关
  2.BnServiceManager同时从IServiceMangager派生,表示它可以直接参与Binder通信
  3.BpServiceManager虽然从BpInterface中派生,但是这条分支似乎与BpBinder没有关系
  4.BnServiceManager是一个虚类,它的业务函数最终需要子类来实现
  5.ServiceManager并没有使用错综复杂的派生关系,它直接打开Binder设别并与之交互

  BpServiceManager既不像它的兄弟BnServiceManager那样与Binder有直接血缘关系,那么怎么和Binder交互?
  BpRefBase中mRemote值就是BpBinder,BpServiceManager左边派生分支树上的一些列代码,它们都是在IService Manager.cpp中:

  BpInterface的实现代码如下:

  BpRefBase()的实现代码如下:

  可以看出是BpServiceMangager的一个变量mRemote指向了BpBinder,回想defaultServiceManger函数,可以得到两个关键对象:
  1.有一个BpBinder对象,它的handle值是0
  2.有一个BpServiceManager对象,它的mRemote值是BpBinder
  BpServiceManager对象实现了IServiceManager的业务函数,现在又有BpBinder作为通信的代表,下面要分析MediaPlayerService的注册过程,进一步分析业务函数的内部是怎么工作的。

2.4 注册MediaPlayerService


1.业务层的工作
  回到main函数,下一个要分析的是MediaPlayerService,代码如下:

  根据前面的分析可知,defaultServiceManager()实际返回的对象是BpServiceManager,它是IServiceManager的后代

  BpServiceManager的addService就是把请求数据打包成data后,传递给BpBinder的transact函数,交给通信层去处理。

2.通信层的工作
  BpBinder和Binder的方式在transact函数中

  在这个里面真正干活的是IPCThreadState,IPCThreadState的实现代码在IPCThreadState.cpp中

  构造函数IPCThreadState()

  每个线程都有一个IPCThreadState,每个IPCThreadState中都有一个mIn、一个mOut,其中,mIn是用来接收自Binder设备的数据的,而mOut则是用来存储发往Binder设备的数据的。

transact
  BpBinder的transact调用的IPCThreadState的transact函数,这个函数实际完成了与Binder通信的工作:

  writeTransactionData函数


  waitForResponse函数


  回复的处理函数executeCommand


  和binder设备的交互,talkwithDriver函数

2.5 StartThread Pool和join Thread Pool分析

  StartThreadPool()函数

  spawnPooledThread()函数

  PoolThread是在IPCThreadState中定义的一个Thread子类:

  joinThreadPool函数的实现:

  到底有多少线程在为Service服务?目前是两个
  1.startThreadPool中新启动的线程通过joinThreadPool读取binder设备,查看是否有请求
  2.主线程调用joinThreadPool读取binder设备,查看是否有请求,binder设备时支持多线程操作的,其中一定时做了同步方面的工作

  我们以MediaServer为例,分析了Binder的机制,这里还是有必要再次强调一下Binder通信和基于Binder通信的业务之间的关系
  1.Binder是通信机制
  2.业务可以基于Binder通信也可使用别的IPC方式通信
Binder之所以复杂,重要原因之一在于Android通过层层封装,巧妙的把通信和业务融合在一起。

以上是关于Android-深入理解Binder的主要内容,如果未能解决你的问题,请参考以下文章

Android-深入理解Binder

深入理解Android跨进程通信-Binder机制

《深入理解Android 卷III》第二章 深入理解Java Binder和MessageQueue

Android Binder原理系统服务的注册过程

Android Binder原理学习Binder前必须要了解的知识点

腾讯面试官:Binder的系统服务是如何获取的?