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_TRANSACTION-----------> ……
|
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,则退出播放动画。
- 打开/dev/binder,用ioctl 检查BINDER_VERSION,设置最大线程数量 BINDER_SET_MAX_THREADS
- startThreadPool() 打开线程池 -> spawnPooledThread(true)
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();
- ProcessState::self(),创建ProcessState对象,打开binder驱动,并设置基本参数
- 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通信
- 主线程也调用了一次 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
法(在服务端的该方法实现是调用
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() 打开线程池 -> spawnPooledThread(true)
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通信并执行命令的循环中