每次看binder相关内容时,都会牵扯到这两个类,每次都看也能理解。不过工作中用的少,脑袋记性不好,所以留下的印象并不是很深刻,这次下定决心,要记下来,下次不翻别人的资料和代码了,直接来瞄一眼自己写的,很快就会回忆起来。
如果说直观印象,我脑袋里立马能跳出来两句话:“启动线程池”,“加入线程池”。然后,我是越来越讨厌自己的囫囵吞枣了,我会逐渐把一切都弄清楚。一点点去地去扩充自己的理解。
每个进程都会有对象的binder守护线程来负责通信,app会有,native进程会有。app进程的binder驱动程序初始化的工作,是在启动app过程中默认完成。native进程一般都是显示调用上面两个类的方法来完成工作。
参考代码:aosp6.0
应用进程的binder初始化
zygote的socket收到system进程发送过来的启动app的消息后,通过fork创建出子进程,这个子进程就是我们需要启动的app进程。子进程创建后,调用 static 方法RuntimeInit.zygoteInit,该方法中,调用 native 方法 nativeZygoteInit(),就是在这个native方法中,完成了binder相关的初始化工作。
该jni方法注册的地方在: framework/base/cor/jni/AndroidRuntime.cpp:
static JNINativeMethod gMethods[] = {
{"nativeZygoteInit", "()V", (void *)com_android_internal_os_RuntimeInit_nativeZygoteInit}
}
native层的实现:
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
gCurRuntime又是什么鬼? “望文生义”一下,应该是 global current runtime,即全局的运行时。定义为:
可以理解为运行环境的上下文,我个人理解,虚拟机(dalvik,art)是这个上下文的组成部分。static AndroidRuntime* gCurRuntime = NULL;
onZygoteInit()的实现在app_main.cpp的AppRuntime类中,该类继承AndroidRuntime。
在onZygoteInit()中,终于看到了这次分析的目标:ProcessState以及该类的方法startThreadPool().virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); }
ALOGV中的信息很明确地说明了,下一步的操作是启动线程池。
ProcessState::self获得了该类的单例对象。
/frameworks/native/libs/binder/ProcessState.cpp:
先判断线程池有没有已经启动,如果没有启动,调用spawnPooledThread(true)来启动。void ProcessState::startThreadPool() { AutoMutex _l(mLock); if (!mThreadPoolStarted) { mThreadPoolStarted = true; spawnPooledThread(true); } }
这里面,启动了一个PoolThread,该类继承自Thread。void ProcessState::spawnPooledThread(bool isMain) { if (mThreadPoolStarted) { String8 name = makeBinderThreadName(); ALOGV("Spawning new pooled thread, name=%s\n", name.string()); sp<Thread> t = new PoolThread(isMain); t->run(name.string()); } }
该类的定义仍在 framework/base/cor/jni/AndroidRuntime.cpp 中class PoolThread : public Thread { public: PoolThread(bool isMain) : mIsMain(isMain) { } protected: virtual bool threadLoop() { IPCThreadState::self()->joinThreadPool(mIsMain); return false; } const bool mIsMain; };
突然间发现,另一个目标出现了:IPCThreadState::self()->joinThreadPool(mIsMain);
frameworks/native/libs/binder/IPCThreadState.cpp:mOut可以理解为和binder驱动共享的消息管道,app进程往里面write消息,binder驱动就会读到。同时,app进程也从mIn里面read从binder驱动中写的消息。void IPCThreadState::joinThreadPool(bool isMain) { mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); ...... status_t result; do { processPendingDerefs(); // now get the next command to be processed, waiting if necessary result = getAndExecuteCommand(); ...... } while (result != -ECONNREFUSED && result != -EBADF); ...... mOut.writeInt32(BC_EXIT_LOOPER); talkWithDriver(false); }
joinThreadPool()方法,中,开始和结束分别执行了一次write操作:mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); 和mOut.writeInt32(BC_EXIT_LOOPER);分别通知binder进入和退出消息循环。在循环过程中,通过getAndExecuteCommand()方法,从mIn中读取消息,并执行相关的命令。getAndExcuteCommand()自然分为两步操作:status_t IPCThreadState::getAndExecuteCommand() { status_t result; int32_t cmd; result = talkWithDriver(); if (result >= NO_ERROR) { ...... result = executeCommand(cmd); ...... } return result; }
1. get: talkWithDriver() // 获取消息2. excute: executeCommand() // 解析出command之后,执行相关操作talkWithDriver()就是用一些文件操作函数读写消息,这里先不表了。以上是应用进程启动binder线程的相关步骤。在我门播放音乐时,是通过binder和media进程里面的一些native service来通信的。这些native进程的binder线程,是怎么启动的呢?就以native media来举例说明:native 进程中的binder的初始化
先谈一下media进程。android很多多媒体相关的服务,都是放在media进程中的。包括audio flinger,media player,camera service等。这个进程,是在init进程中启动的。service media /system/bin/mediaserver class main user media group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm ioprio rt 4
进程名称:media,可执行的程序地址:/system/bin/mediaserver代码路径:frameworks/ava/media/mediaserver/main_mediaserver.cpp入口函数当然是main():这里面,先后启动了一些media service,然后就很直接到调用了ProcessState的startThreadPool()和IPCThreadState的joinThreadPool().这样,我们在app中int main(int argc __unused, char** argv) { signal(SIGPIPE, SIG_IGN); char value[PROPERTY_VALUE_MAX]; bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1); pid_t childPid; if (doLog && (childPid = fork()) != 0) { } else { .... InitializeIcuOrDie(); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); ALOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate(); MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); SoundTriggerHwService::instantiate(); RadioService::instantiate(); registerExtensions(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } }
请求的一些media相关的服务,在media server进程中就会通过binder线程得知,从而执行相关的任务,完成后,把结果或者执行状态再通过binder返回到app进程中。以上就是在应用进程中和native进程中,binder线程的大概的启动过程。