Native层流程大纲
介绍完Binder驱动的构架后,下面我们进入到Binder Native层的流程分析。Binder的整体流程可分为如下几个步骤:
其中,第2步是3和4的基础。上面4个步骤,是系统中Binder驱动和Native层的主要工作,而Binder Java层的每次调用底层函数都离不开这4步的操作。这里介绍Native层,Java层将在下章节介绍。
4.1 SM成为守护进程
SM成为守护进程的过程中,与驱动交互频繁,下面会结合之前的驱动框架来分析:
- 打开Binder设备文件;
- 调用mmap
- 告诉Binder驱动程序自己是Binder上下文管理者,即我们前面所说的守护进程;
- 进入一个无穷循环,充当Server的角色,等待Client的请求
4.1.1打开Binder设备文件
在service_manager.c打开Binder设备文件的核心代码见下图:
函数首先是执行打开Binder设备文件的操作binder_open,这个函数位于frameworks/base/cmds/servicemanager/binder.c文件中, 代码如下:
主要做了2件主要的事情:
4.1.2 打开设备详细分析
4.1.3 成为守护进程
回到frameworks/base/cmds/servicemanager/service_manager.c文件中的main函数,下一步就是调用binder_become_context_manager来通知Binder驱动程序自己是Binder机制的上下文管理者,即守护进程。
binder_become_context_manager函数位于frameworks/base/cmds/servicemanager/binder.c文件中,
这里通过调用ioctl文件操作函数来通知Binder驱动程序自己是守护进程,命令号是BINDER_SET_CONTEXT_MGR,流程如下:
4.1.4进入loop循环
回到frameworks/base/cmds/servicemanager/service_manager.c文件中的main函数中,继续往下看,会看到调用了binder_loop()函数进入循环,等待Client来请求。
binder_loop函数定义在frameworks/base/cmds/servicemanager/binder.c文件中,流程如下:
4.1.5 SM成为守护进程-总结
至此,我们就从源代码一步一步地分析完Service Manager是如何成为Android进程间通信(IPC)机制Binder守护进程的了。总结一下,Service Manager是成为Android进程间通信(IPC)机制Binder守护进程的过程是这样的:
1. 打开/dev/binder文件:open("/dev/binder", O_RDWR);
2. 建立128K内存映射:mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
3. 通知Binder驱动程序它是守护进程:binder_become_context_manager(bs);
4. 进入循环等待请求的到来:binder_loop(bs, svcmgr_handler);
在这个过程中,在Binder驱动程序中建立了一个struct binder_proc结构、一个struct binder_thread结构和一个struct binder_node结构,这样,Service Manager就在Android系统的进程间通信机制Binder担负起守护进程的职责了。
4.2 Server和Client获得Service Manager远程接口
我们知道,Service Manager在Binder机制中既充当守护进程的角色,同时它也充当着Server角色,然而它又与一般的Server不一样。对于普通的Server来说,Client如果想要获得Server的远程接口,那么必须通过Service Manager远程接口提供的getService接口来获得,这本身就是一个使用Binder机制来进行进程间通信的过程。而对于Service Manager这个Server来说,Client如果想要获得Service Manager远程接口,却不必通过进程间通信机制来获得,因为Service Manager远程接口是一个特殊的Binder引用,它的引用句柄一定是0。
获取Service Manager远程接口的函数是defaultServiceManager,这个函数声明在frameworks/base/include/binder/IServiceManager.h文件中:
4.2.1 Service Manager继承关系
那么为什么要获取远程端口呢?!是因为要实现业务以及完成通信。先来看看网上的一个关于继承关系的图示:
IServiceManager类提供的业务函数:getService(), checkService(), addService();
BpServiceManager类继承了BpInterface类,而BpInterface类继承了BpRefBase类。
在BpRefBase类中,有一个成员变量mRemote,它的类型是IBinder*,实现类为BpBinder,它表示一个Binder引用,引用句柄值保存在BpBinder类的mHandle成员变量中。
BpBinder类通过IPCThreadState类来和Binder驱动程序并互,而IPCThreadState又通过它的成员变量mProcess来打开/dev/binder设备文件,mProcess成员变量的类型为ProcessState。
ProcessState类打开设备/dev/binder之后,将打开文件描述符保存在mDriverFD成员变量中,以供后续使用。
4.2.2 defaultServiceManager
理清了上述的继承关系后,我们再来看看defaultServicemanager这个函数。
从这个函数可以看出:gDefaultServiceManager是单例模式,调用defaultServiceManager函数时,如果gDefaultServiceManager已经创建,则直接返回,否则通过interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL))来创建一个,并保存在gDefaultServiceManager全局变量中。
在这个过程中,有4个关键步骤:
下面来分析这4个步骤
4.2.2.1 ProcessState::self()
ProcessState::self()是ProcessState的静态成员函数,它的作用是返回一个全局唯一的ProcessState实例变量,就是单例模式了,这个变量名为gProcess。如果gProcess尚未创建,就会执行创建操作,在ProcessState的构造函数中,会通过open文件操作函数打开设备文件/dev/binder,并且返回来的设备文件描述符保存在成员变量mDriverFD中。也就是得到了一个可以和底层打交道的ProcessState类型的gProcess对象。在addervice()的流程里,会深入分析。
4.2.2.2 getContextObject()
gProcess->getContextObject(NULL),传递的值为NULL即0,返回的值为sp<IBinder>类型的getStrongProxyForHandle(0)。getStrongProxyForHanlde(int32_t handle)中,handle的值是一个资源项数组中的索引值。
结果为:返回一个handle为0的Binder引用,即BpBinder;于是创建Service Manager远程接口的语句可以简化为:gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));
4.2.2.3 interface_cast
再来看函数interface_cast<IServiceManager>的实现,它是一个模板函数,定义在framework/base/include/binder/IInterface.h文件中:
这里的《INTERFACE>是IServiceManager,于是调用了IServiceManager::asInterface函数,那么 gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0)); 可以变成:gDefaultServiceManager = IServiceManager::asInterface(new BpBinder(0));
IserviceManager::asInterface是通过DECLARE_META_INTERFACE(ServiceManager)宏在IServiceManager类中声明的,它位于framework/base/include/binder/IServiceManger.h文件中。IServiceManager::asInterface的实现是通过IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")宏定义的,它位于framework/base/libs/binder/IServiceManager.cpp文件中。
4.2.2.4 IServiceManager::asInterface
最终,在IServiceManager::asInterface函数中会调用:Return intr = new BpServiceManager(obj); 这里的obj就则刚才创建的new BpBinder(0),上面的代码为:
回到defaultServiceManager函数中,最终结果为:gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
这样,Service Manager远程接口就创建完成了,它本质上是一个BpServiceManager,包含了一个句柄值为0的Binder引用。这里,实现asInterface函数,是利用BpBinder对象新建了一个BpServiceManager对象
4.3 Server向SM注册服务
实际上,BnMediaPlayerService并不是直接接收到Client处发送过来的请求,而是使用了IPCThreadState接收Client处发送过来的请求,而IPCThreadState又借助了ProcessState类来与Binder驱动程序交互。
IPCThreadState接收到了Client处的请求后,就会调用BBinder类的transact函数,并传入相关参数,BBinder类的transact函数最终调用BnMediaPlayerService类的onTransact函数,于是,就开始真正地处理Client的请求了。
以MediaServer作为Server的例子,这里我们只看MediaPlayerService:多媒体系统的重要服务。MS的入口函数在 \frameworks\av\media\mediaserver\ main_mediaserver.cpp 如下图,
可分为5步:
下面来分别分析。
4.3.1 ProcessState
之前分析过,这里详细介绍下参数传递的流程。ProcessState::self()调用创建一个ProcessState实例。ProcessState::self()是ProcessState类的一个静态成员变量,定义在frameworks/base/libs/binder/ProcessState.cpp文件中:
这里可以看出,这个函数作用是返回一个全局唯一的ProcessState实例gProcess。全局唯一实例变量gProcess定义在frameworks/base/libs/binder/Static.cpp文件中
再来看ProcessState的构造函数:ProcessState::ProcessState()的流程:
这样,ProcessState全局唯一变量gProcess就创建完毕了,回到了frameworks/base/media/mediaserver/main_mediaserver.cpp文件中的main函数
4.3.2 创建IServiceManager对象
DefaultServiceManager函数的实现在之前分析过,则:sp<IServiceManager> sm = defaultServiceManager(); 为:sp<IServiceManager> sm = new BpServiceManager(new BpBinder(0));
4.3.3 注册MediaPlayerService
MediaPlayerService::instantiate()调用:defaultServiceManager()->addService()。这个函数最终会通过IPCthreadState->transact()和Binder驱动打交道,把数据传送到SM中,完成MediaPlayerService的注册。defaultServiceManager()返回的对象是BpServiceManager,而BpServiceManager是IServiceManager的后代。IServiceManager是一个抽象类,里面有我们操作业务层的各种函数。
4.3.3.1 MediaPlayerService::instantiate()
MediaPlayerService::instantiate();的实现如下:
这里,实际上是调用的BpServiceManger::addService()这个函数实现在frameworks/base/libs/binder/IServiceManager.cpp文件中的addService()。addService是一个业务层的函数,调用remote()->transact();remote()返回的是mRemote,也就是BpBinder对象。在addService函数中,把请求数据打包成data后,传递给了BpBinder的transact函数,把通信任务交给了BpBinder;即交给了通信层去处理。
4.3.3.2 transact()通信层的工作
BpBinder::transact()调用了:status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
这里的mHandle为0,code为ADD_SERVICE_TRANSACTION。ADD_SERVICE_TRANSACTION是上面以参数形式传进来的,这里表示的是Service Manager远程接口,mHandle的句柄值一定是0。即,把transact工作交给了IPCThreadState。IPCThreadState::self()中,TLS: Thread Local Storage,每个线程都有,且不共享。通过pthread_getspecific/pthread_setspecific函数可以获得/设置这些空间中的内容。
流程如下:
4.3.4 StartThreadPool()
StartThreadPool()调用spawnPooledThread()函数:sp<Thread> t = new PoolThread(isMain); isMain参数是true; PoolThread是在IPCThreadState中定义了一个Thread子类。PoolThread类中,调用threadLoop()。threadLoop()中,在这个线程中又创建了一个IPCThreadState: IPCThreadState::self()->joinThreadPool(mIsMain)。
joinThreadPool()流程:
4.3.5 MS中的joinThreadPool()
MediaServer进程一共注册了4个服务。MS中目前有两个线程在talkWithDriver():
BnService和BpService负责业务的交互;BBinder和BpBinder负责通信的交互
4.3.6 MediaServer注册服务到SM流程图
4.4 Client从SM获得服务
client从SM获得服务,也就是从SM获得 BpMediaPlayerService。BpMediaPlayerService的构造函数有一个参数impl,它的类型为const sp<IBinder>&,从上面的描述中,这个实际上就是一个BpBinder对象。这样,要创建一个BpMediaPlayerService对象,首先就要有一个BpBinder对象。再来看BpBinder类的构造函数,它有一个参数handle,类型为int32_t,这个参数的意义就是请求MediaPlayerService这个远程接口的进程对MediaPlayerService这个Binder实体的引用了。因此,获取MediaPlayerService这个远程接口的本质问题就变为从Service Manager中获得MediaPlayerService的一个句柄了。
4.4.1 详细分析:
这里我们以MediaServer中的MediaPlayService与Client交互为例,来了解请求数据是如何从通信层传递到业务层并进行处理的:
client想要获得某个Service的信息,就得先和SM交互,通过调用getService()来获得对应的Service信息,这里用到的是IMediaDeathNotifier::getMeidaPlayerService()
有了BpMediaPlayerService,client就能够使用任何IMediaPlayerService提供的业务逻辑函数了,e.g: createMediaRecorder和createMetadataRetriever等。调用这些函数都将把请求数据打包发给Binder驱动,并由BpBinder中handle知道对应端的处理者来处理,包括
BpServiceManager::getService通过BpServiceManager::checkService执行操作。
在BpServiceManager::checkService中: