Bn Bp Binder native层关系

Servicemanager

源码在/frameworks/base/cmds/servicemanager/service_manager.c

编译成 systemmanager 可执行文件

systemmanager是以binder为主要通信手段,为系统各种各样服务的进行登记查询管理的服务。

系统服务的框架里有3个主要角色,服务提供者(server),服务使用者(client),和服务管理者(system manager),通信方式是Binder,在系统启动流程中的先后顺序是:服务管理者,服务提供者,服务使用者。

 

成为system manager

该进程会常驻在系统中,先通过binder_become_context_manager()注册为系统中服务管理器(本质上是通过ioctl对打开的/dev/binder的fd发送BINDER_SET_CONTEXT_MGR),然后通过binder_loop() 进入死循环,来持续为系统系统各种服务的查询/添加功能。各个服务本身运行在自己的进程中,但是通过systemmanager这样一个枢纽,提供真实服务的进程,将自己的服务向systemmanager注册,然后其他需要使用服务的进程通过先从/dev/binder中获取到systemmanager,然后再通过systemmanager查询并获取到真正想要的服务的stub,然后包装成binderPoxy(bpbinder),然后通过这个bpbinder与真正的服务进行IPC通信。

 

用在服务提供者和服务使用者角色中,与system manager 进行通信的模块:IPCThreadState ProcessState

其他服务使用者通过在自己的进程中调用ProcessState::self()获得一个ProcessState对象(进程级单例,单例对象定义在binder/Static.cppg Process;)(一般是使用IPCThreadState对象时间接初始化,IPCThreadState的使用非常广泛,如Looper的native层,BPBinder中,bootanimation服务,app_process中当虚拟机状态发生改变后用来关闭binder的fd等,只要是native层,几乎都会使用到这个类来进行binder的IPC通信),在构造函数中ProcessState.cpp open_driver()打开/dev/binder 的fd,然后通过mmap映射这个fd的BINDER_VM_SIZE 大小的到自己进程中。

之后,往往通过调用joinThreadPool(isMain = 默认true)方法和binder的驱动进行交互并初始化,让当前进程在serviciemanager处注册服务,方法内部通过mOut和mIn 这2个Parcel数据对象(提供了将数据按规定格式(如Int32,float等)进行读写的方法,各种通信状态的记录等)来向binder收发数据,首先构造mOut写入Int32 BC_ENTER_LOOPER,然后进入一个循环中,先对mIn的数据处理,然后调用talkWithDriver()(本质上是通过ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)与binder通信,bwr结构是又一次对mIn和mOut的数据转换,是直接和binder驱动进行IO的数据结构,一次这样的ioctl既可以用作向binder写数据,也可以从binder读数据,是否存在读的数据需要看上下文以及外部环境是否有信息发送过来) 来和binder驱动通信),获得状态对象,然后从mIn读取cmd,然后执行executeCommand(cmd);根据cmd的类型执行回馈处理命令,将mIn的数据出,将处理好的数据放入mOut打包,等下次talkWithDriver()的时候和binder回复以及接受新命令(mIn头部的int32大小的数据存放cmd)。joinThreadPool中的这个处理binder数据的循环会运行到executeCommand() 返回 TIMED_OUT 或者ECONNREFUSED等失败退出的状态为止,退出循环,最后通过向mOut写入 (BC_EXIT_LOOPER并调用talkWithDriver(false来结束通信。

 

SystemServer的分析,主要流程

Main()

加载 android_servers 动态库

1. 进入 init1(args) native方法(主要启动本机服务SurfaceFlinger(屏幕)AudioFlinger,传感器等,设置通过binder监听随着servicemanager死亡的而自杀)

2. 之后调用init2()启动android服务

a) 设置进程,线程优先级

b) 检查 sys.shutdown.requested, =1重启,或关机

c) 启动一堆核心服务,并注册(如PowerManagerService,ActivityManager等)

若设置了 vold.decrypt  ENCRYPTING  ENCRYPTED(加密状态 则设置只运行 coreApp,以此启动packageManager

。。。服务。。。。

d) 启动一些需要UI的非核心服务,并注册,大多数服务类似am,驻留在当前system_service 进程里,不像c层服务,大多数是自己独立一个进程

e) 根据当前是否为安全模式,进行不同的初始化

f) 启动其他app 进程,如devicePolicy

g) 注册am中的一个回调systemReady,在回调中 调用一堆服务的 systemReady方法

3. 循环处理binder命令(注册了自己的服务?)

 

Init1 对应源码在

/frameworks/base/services/jni/com_android_server_SystemServer.cpp

 

省略源码+注释若干

 

下面是java层的system_server的总结

java层的system_server启动了并注册和启动了很多java层服务(各个服务自己有一条线程来维持与binder通信和执行业务),进入了一个Looper循环(作用?)

System_server 中的很多服务都是在java层初始化,并驻留在system_server进程中(通过一条单独处理binder通信的线程来维持运作,如activityManager),然后注册到serviceManager

init中也有服务的概念,这些服务中有一部分不会注册到servcieManager如ueventd,healthd ,但也有一部分会启动后以c层代码的方式注册到服务,如bootanimation

所以说关于服务有3类

1. Init中启动的native层服务,不注册到serviceManager

2. Init中启动的native层服务,会注册到serviceManager

3. System_server中启动的java层服务,会注册到serviceManager

 

 

 

 

 

 

Binder

IPCThreadState中joinThreadPool 与binder通信某些地方有点类似与TCP通信,一方发送一个Command(字符串BC_*的命令),另一方接收到并处理完后,返回一个return(字符串BR_*)状态,类似TCP的发送某SEQ帧后,接收方收到后回馈一个对应的ACK帧

 

一次向servicemanager添加注册服务需要经过多层

Binder驱动层,binder驱动通信层,servicemanager业务层,具体的执行注册服务的函数。4层

关键通信函数及一些常量

Binder驱动,ProcessState, ioctl()

IPCThreadState::executeCommand()

svcmgr_handler()

do_add_service()

BINDER_VERSION

BINDER_WRITE_READ---->

BINDER_THREAD_EXIT

BINDER_SET_CONTEXT_MGR

……

BR_INCREFS

BR_TRANSACTION_COMPLETE

BR_TRANSACTION----------->

BR_REPLY

……

 

SVC_MGR_GET_SERVICE

SVC_MGR_CHECK_SERVICE

SVC_MGR_ADD_SERVICE---->

……

svc_can_register()呼叫者uid权限校验

……

加入服务到svclist链表中

……

 

 

 

 

 

小结:

起点:

I##自定义INTERFACE服务类接口    : IInterface

 

。。。

 

上面画的线图,格式毁了,看截图把

 

 

 

 

 

 

浓缩:

IBinder有2个主要的子类BBinder 和 BpBinder

1.服务端继承BBinder实现transact用于在onTransact里根据cmd调用实际的接口实现的方法然后通过IPCThreadState的talkWithDriver写回结果给binder

2.客户端继承BpBinder实现transact用于根据调用的业务方法产生对应cmd和参数调用IPCThreadState::self()->transact(),然后通过waitForResponse() -> talkWithDriver() binder通信

3.Binder驱动和servicemanager做的工作主要是使用内存共享完成IPC,另外一个是在客户端获取服务的IBinder时,用BpBinder*的实现,而不是服务器端添加服务时给出的BBinder*。

4.当前是否服务端还是客户端?

servicemanager通过binder通信获取到某个服务的IBinder指针后,是在interface_cast()调用的asInterface()中根据这个IBinder的queryLocalInterface() 返回IInterface* 是否为0指针来判断的

queryLocalInterface()返回是否为0指针

queryLocalInterface 是声明在IBinder中的一个虚方法,有一个默认实现(客户端中的情况)在Binder.cpp 中实现 IBinder::queryLocalInterface() (总是返回NULL)

queryLocalInterface 在服务端在BnInterface中覆盖默认的实现

服务端是调用方法IBinder->BBinder->BnInterface::queryLocalInterface(),查询用的 (用MediaPlayService举例)IMediaPlayService::descriptor == MediaPlayService::descriptor (MediaPlayService::descriptor是MediaPlayService通过继承IMediaPlayService得来,是同一个类中的成员),所以返回 this对象的指针地址,不为0

 

这一部分和java层的binder机制是类似的(为了方便程序员使用Binder,android提供的AIDL的主要功能就是在此层,根据自定义方法的数量生成等量的常量,用在BINDER_WRITE_READ  -> BR_TRANSACTION binder通信时确定远端让本方调用某个本地方法的 COMMAND 常量,然后根据command常量调用对应的方法。类似svcmgr_handler()中做的工作。)

 

 

 

对象转换过程:

IserviceManager <- IBinder <- BpBinder 

 

服务使用:

 

 

IPCThreadState,ProcessState,android::Thread, android::Thread::threadLoop(), binder. 这一切是有关联的

 

binder – ProcessState - android::Thread – IPCThreadState

简要流程

Binder

打开/dev/binder ,用ioctl 循环的BINDER_WRITE_READ 进行数据读写并执行对应的命令

 

ProcessState

主要持有/dev/binder的fd,设置与binder通信的基本参数

 

分析一个 开机动画的例子 bootanimation

在void SurfaceFlinger::startBootAnim()中

调用property_set("ctl.start", "bootanim"); 通过属性服务 发送控制命令 启动bootanim 服务,播放启动动画,之后当SurfaceFlinger::bootFinished()启动完成后,调用property_set("service.bootanim.exit", "1"); 设置动画退出属性为1,bootanimation会轮询检测该标志,若读取到1,则退出播放动画。

  1. 打开/dev/binder,用ioctl 检查BINDER_VERSION,设置最大线程数量 BINDER_SET_MAX_THREADS
  2. startThreadPool() 打开线程池 -> spawnPooledThreadtrue)

1. new 一个PoolThread 线程对象(继承android::Thread ,class Thread : virtual public RefBase, android::Thread的线程功能实际上是用pthread实现的),设置线程名称为Binder Thread 1

2. 调用PoolThread run方法,实际上是调用了android::Thread::run() -> androidSetCreateThreadFunc() -> pthread_create() -> Thread::_threadLoop() -> PoolThread::readyToRun() -> PoolThread::threadLoop()

mCanCallJava = isMain = true

androidCreateThreadEtc()

默认是 gCreateThreadFn = androidCreateRawThreadEtc; 

有个别地方 AndroidRuntime.cpp 中通过  androidSetCreateThreadFunc()  gCreateThreadFn 指向了 javaCreateThreadEtc() ,但其实际上做了一些对JVM的额外处理后又进入了androidCreateRawThreadEtc

androidCreateRawThreadEtc 的实现分为 LINUX 下的 PTHREAD 实现 和 WIN32_THREAD 实现,这里是LINUX的实现

最关键的则是int result = pthread_create(&thread, &attr, (android_pthread_entry)entryFunction, userData);

而入口函数entryFunction 则是在 Thread::run() 中指定的Thread::_threadLoop(),此时子线程才真正跑起来

之后做了一些初始化如gettid()等,进入了一个循环,第一次进入循环则调用readyToRun()虚方法(一般由继承Thread的子类自己根据业务逻辑实现,比如BootAnimation::readyToRun()中当图形绘制的初值化工作完成后返回NO_ERROR,否则返回NO_INIT),然后android Thread框架检测,如果是 NO_ERROR 并且exitPending()未返回true,那么就调用 虚方法threadLoop();(注意,该方法不是_threadLoop()),该方法内一般让子类实现关键的业务逻辑,如BootAnimation::threadLoop()中就在进入一个死循环,播放开机动画,直到exitPending()返回true(当调用了requestExit()后exitPending会返回true,本质上是将mExitPending 变量赋值为true)后退出循环停止播放动画。

因为这里的特定子类是PoolThread所以Thread::_threadLoop()这个框架方法调用了PoolThread::readyToRun(),但PoolThread没去重写它,所以默认返回NO_ERROR,继续,调用PoolThread::threadLoop(), 调用IPCThreadState::self()->joinThreadPool(mIsMain = true); self()方法 主要是通过pthread_getspecific 获取保存的线程私有数据中IPCThreadState 对象的指针,如果没有获取到则新建一个IPCThreradState 对象并用pthread_key_create() pthread_setspecific() 对象指针存入线程私有数据集合,然后进入joinThreadPool()

IPCThreadState的executeCommand() 主要实现了和通过binder通信的一些常用命令,如获取/释放 自身服务的BBinder对象指针,增/减引用计数器,这里主要是对BR_*的反馈命令进行处理。BC_*发给binder,binder或远端服务返回一个BR_*。

Bootnimation 被 new 出来后,被第一次引用时,会触发onFirstRef()的回调,这里是bootanimation对象业务逻辑的的入口,在里面调用了run() 启动Bootnimation这个继承了Thread类的子线程,并进入threadLoop()根据当前启动阶段展示开机动画

 

 

总结:

ProcessState – PoolThread – IPCThreadState 这几个类常用在底层做binder通信使用

 

 

常见用法:

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

 

  1. ProcessState::self(),创建ProcessState对象,打开binder驱动,并设置基本参数
  2. ProcessState::startThreadPool(), 启动一个PoolThread子线程,调用run()让子线程初始化并进入ProcessState::threadLoop() 该方法中调用IPCThreadState::self()->joinThreadPool(mIsMain) ,让子线程在一个循环内通过talkWithDriver() binder、servicemanager、服务进程进行通信,并用executeCommand() 根据具体的反馈cmd执行处理命令,让这个子线程成为与binder通信的专用线程。

ProcessState::startThreadPool() =

-> new PoolThread子线程 并让它

-> Thread::run()

-> PoolThread::threadLoop()

-> IPCThreadState::self()->joinThreadPool(mIsMain) 循环的与binder通信

  1. 主线程也调用了一次 IPCThreadState::self()->joinThreadPool(); 那么主线程也进入与binder通信并执行命令的循环中

 

 

 

 

 

 

 

 

 

 

.doc文件的格式直接复制过来,有些对不上,所以截图

 

 

 

 

 

 

 

 

 

 

 

小结:

起点:

I##自定义INTERFACE服务类接口    : IInterface

|

V

.h文件中DECLARE_META_INTERF         asBinder()

ACE(INTERFACE) 声明asInterface()

以及声明自定义的业务方法。

.c 文件中使用

IMPLEMENT_META_INTERFACE 实现

AsInterface()方法

 

此处调用发起是,IPCThreadState

调用了joinThread后(PoolThread)

,在一个循环中处理binder发来

的消息,并进入executeCommand()

,其中cmd为BR_TRANSACTION

case里,会调用the_context_object

tr中的 BBinder* b->transact

法(在服务端的该方法实现是调用

onTransact,客户端的BpBinder

是直接与binder用ioctl通信)

^

|

实现BBinder::onTransact 传递给addService

                           根据传入参数解cmd(code)  

真正实现接口(I##自定义    调用当前对象中自定义INTE

INTERFACE服务类接口)中   RFACE服务类对应的方法,拿

的方法的业务逻辑           到返回值后写入reply对象                                                                                        

^ß---------------------------/    ^

|                                  |

自定义INTERFACE服务类 : Bn自定义INTERFACE服务  : BnInterface   : I##自定义INTERFACE服务类接口:(IInterface)  : BBinder : IBinder  : RefBase

   Bp自定义INTERFACE服务  : BpInterface   : I##自定义INTERFACE服务类接口:(IInterface)                        : BpRefBase     --    BpBinder   :   IBinder

|                                                          |

V                                                          V

实现INTERFACE方法,但                           客户端拿到servicemanager通过binder返回过来的                          保存binder返回的IBin 

是通过调用内部保存的                             IBinder后,调用asInterface转换为I##自定义                            der(BpBinder)指针

IBinder(BpBinder)                              INTERFACE服务类接口对象,直接调用想用的业务方法

transact方法通过    《-----------------------  Bp自定义INTERFACE服务 中的实现

Binder通信(ioctl                              

完成数据转发给服务

BBinder的

onTransact处理并返回

 

 

浓缩:

IBinder有2个主要的子类BBinder 和 BpBinder

1.服务端继承BBinder实现transact用于在onTransact里根据cmd调用实际的接口实现的方法然后通过IPCThreadState的talkWithDriver写回结果给binder

2.客户端继承BpBinder实现transact用于根据调用的业务方法产生对应cmd和参数调用IPCThreadState::self()->transact(),然后通过waitForResponse() -> talkWithDriver() binder通信

3.Binder驱动和servicemanager做的工作主要是使用内存共享完成IPC,另外一个是在客户端获取服务的IBinder时,用BpBinder*的实现,而不是服务器端添加服务时给出的BBinder*。

4.当前是否服务端还是客户端?

servicemanager通过binder通信获取到某个服务的IBinder指针后,是在interface_cast()调用的asInterface()中根据这个IBinder的queryLocalInterface() 返回IInterface* 是否为0指针来判断的

queryLocalInterface()返回是否为0指针

queryLocalInterface 是声明在IBinder中的一个虚方法,有一个默认实现(客户端中的情况)在Binder.cpp 中实现 IBinder::queryLocalInterface() (总是返回NULL)

queryLocalInterface 在服务端在BnInterface中覆盖默认的实现

服务端是调用方法IBinder->BBinder->BnInterface::queryLocalInterface(),查询用的 (用MediaPlayService举例)IMediaPlayService::descriptor == MediaPlayService::descriptor (MediaPlayService::descriptor是MediaPlayService通过继承IMediaPlayService得来,是同一个类中的成员),所以返回 this对象的指针地址,不为0

 

这一部分和java层的binder机制是类似的(为了方便程序员使用Binder,android提供的AIDL的主要功能就是在此层,根据自定义方法的数量生成等量的常量,用在BINDER_WRITE_READ  -> BR_TRANSACTION binder通信时确定远端让本方调用某个本地方法的 COMMAND 常量,然后根据command常量调用对应的方法。类似svcmgr_handler()中做的工作。)

 

 

 

 

对象转换过程:

IserviceManager <- IBinder <- BpBinder 

 

 

服务注册:

 

服务使用:

 

 

 

IPCThreadState,ProcessState,android::Thread, android::Thread::threadLoop(), binder. 这一切是有关联的

 

binder  ProcessState - android::Thread  IPCThreadState

简要流程

Binder

打开/dev/binder ,用ioctl 循环的BINDER_WRITE_READ 进行数据读写并执行对应的命令

 

ProcessState

主要持有/dev/binder的fd,设置与binder通信的基本参数

 

分析一个 开机动画的例子 bootanimation

void SurfaceFlinger::startBootAnim()

调用property_set("ctl.start", "bootanim"); 通过属性服务 发送控制命令 启动bootanim 服务,播放启动动画,之后当SurfaceFlinger::bootFinished()启动完成后,调用property_set("service.bootanim.exit", "1"); 设置动画退出属性为1,bootanimation会轮询检测该标志,若读取到1,则退出播放动画。

1. 打开/dev/binder,用ioctl 检查BINDER_VERSION,设置最大线程数量 BINDER_SET_MAX_THREADS

2. startThreadPool() 打开线程池 -> spawnPooledThreadtrue)

1. new 一个PoolThread 线程对象(继承android::Thread ,class Thread : virtual public RefBase, android::Thread的线程功能实际上是用pthread实现的),设置线程名称为Binder Thread 1

2. 调用PoolThread run方法,实际上是调用了android::Thread::run() -> androidSetCreateThreadFunc() -> pthread_create() -> Thread::_threadLoop() -> PoolThread::readyToRun() -> PoolThread::threadLoop()

mCanCallJava = isMain = true

androidCreateThreadEtc()

默认是 gCreateThreadFn = androidCreateRawThreadEtc; 

有个别地方 AndroidRuntime.cpp 中通过  androidSetCreateThreadFunc()  gCreateThreadFn 指向了 javaCreateThreadEtc() ,但其实际上做了一些对JVM的额外处理后又进入了androidCreateRawThreadEtc

androidCreateRawThreadEtc 的实现分为 LINUX 下的 PTHREAD 实现 和 WIN32_THREAD 实现,这里是LINUX的实现

最关键的则是int result = pthread_create(&thread, &attr, (android_pthread_entry)entryFunction, userData);

而入口函数entryFunction 则是在 Thread::run() 中指定的Thread::_threadLoop(),此时子线程才真正跑起来

之后做了一些初始化如gettid()等,进入了一个循环,第一次进入循环则调用readyToRun()虚方法(一般由继承Thread的子类自己根据业务逻辑实现,比如BootAnimation::readyToRun()中当图形绘制的初值化工作完成后返回NO_ERROR,否则返回NO_INIT,然后android Thread框架检测,如果是 NO_ERROR 并且exitPending()未返回true,那么就调用 虚方法threadLoop();(注意,该方法不是_threadLoop()),该方法内一般让子类实现关键的业务逻辑,如BootAnimation::threadLoop()中就在进入一个死循环,播放开机动画,直到exitPending()返回true(当调用了requestExit()后exitPending会返回true,本质上是将mExitPending 变量赋值为true)后退出循环停止播放动画。

因为这里的特定子类是PoolThread所以Thread::_threadLoop()这个框架方法调用了PoolThread::readyToRun(),但PoolThread没去重写它,所以默认返回NO_ERROR,继续,调用PoolThread::threadLoop(), 调用IPCThreadState::self()->joinThreadPool(mIsMain = true); self()方法 主要是通过pthread_getspecific 获取保存的线程私有数据中IPCThreadState 对象的指针,如果没有获取到则新建一个IPCThreradState 对象并用pthread_key_create() pthread_setspecific() 对象指针存入线程私有数据集合,然后进入joinThreadPool()

IPCThreadState的executeCommand() 主要实现了和通过binder通信的一些常用命令,如获取/释放 自身服务的BBinder对象指针,增/减引用计数器,这里主要是对BR_*的反馈命令进行处理。BC_*发给binder,binder或远端服务返回一个BR_*。

Bootnimation 被 new 出来后,被第一次引用时,会触发onFirstRef()的回调,这里是bootanimation对象业务逻辑的的入口,在里面调用了run() 启动Bootnimation这个继承了Thread类的子线程,并进入threadLoop()根据当前启动阶段展示开机动画

 

 

总结:

ProcessState  PoolThread  IPCThreadState 这几个类常用在底层做binder通信使用

 

 

常见用法:

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

 

1. ProcessState::self(),创建ProcessState对象,打开binder驱动,并设置基本参数

2. ProcessState::startThreadPool(), 启动一个PoolThread子线程,调用run()让子线程初始化并进入ProcessState::threadLoop() 该方法中调用IPCThreadState::self()->joinThreadPool(mIsMain) ,让子线程在一个循环内通过talkWithDriver() binder、servicemanager、服务进程进行通信,并用executeCommand() 根据具体的反馈cmd执行处理命令,让这个子线程成为与binder通信的专用线程。

ProcessState::startThreadPool() =

-> new PoolThread子线程 并让它

-> Thread::run()

-> PoolThread::threadLoop()

-> IPCThreadState::self()->joinThreadPool(mIsMain) 循环的与binder通信

3. 主线程也调用了一次 IPCThreadState::self()->joinThreadPool(); 那么主线程也进入与binder通信并执行命令的循环中

 

posted on 2019-10-30 14:40  jald  阅读(1206)  评论(0编辑  收藏  举报

导航