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 卷III》第二章 深入理解Java Binder和MessageQueue