深入理解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通过层层封装,巧妙的把通信和业务融合在一起。 
|