您的位置:首页 > 其它

binder 与 ProcessState & IPCThreadState

2016-11-08 17:15 567 查看
每次看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,即全局的运行时。定义为:
static AndroidRuntime* gCurRuntime = NULL;
可以理解为运行环境的上下文,我个人理解,虚拟机(dalvik,art)是这个上下文的组成部分。
onZygoteInit()的实现在app_main.cpp的AppRuntime类中,该类继承AndroidRuntime。
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
在onZygoteInit()中,终于看到了这次分析的目标:ProcessState以及该类的方法startThreadPool().
ALOGV中的信息很明确地说明了,下一步的操作是启动线程池。
ProcessState::self获得了该类的单例对象。
/frameworks/native/libs/binder/ProcessState.cpp:
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
先判断线程池有没有已经启动,如果没有启动,调用spawnPooledThread(true)来启动。
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());
}
}
这里面,启动了一个PoolThread,该类继承自Thread。
该类的定义仍在 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:
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 necessaryresult = getAndExecuteCommand();......} while (result != -ECONNREFUSED && result != -EBADF);......mOut.writeInt32(BC_EXIT_LOOPER);talkWithDriver(false);}
mOut可以理解为和binder驱动共享的消息管道,app进程往里面write消息,binder驱动就会读到。同时,app进程也从mIn里面read从binder驱动中写的消息。
joinThreadPool()方法,中,开始和结束分别执行了一次write操作:
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);和
mOut.writeInt32(BC_EXIT_LOOPER);
分别通知binder进入和退出消息循环。
在循环过程中,通过getAndExecuteCommand()方法,从mIn中读取消息,并执行相关的命令。
status_t IPCThreadState::getAndExecuteCommand(){status_t result;int32_t cmd;result = talkWithDriver();if (result >= NO_ERROR) {......result = executeCommand(cmd);......}return result;}
getAndExcuteCommand()自然分为两步操作:
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/mediaserverclass mainuser mediagroup audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrmioprio rt 4
进程名称:media,可执行的程序地址:/system/bin/mediaserver
代码路径:frameworks/ava/media/mediaserver/main_mediaserver.cpp
入口函数当然是main():
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 service,然后就很直接到调用了ProcessState的startThreadPool()和IPCThreadState的joinThreadPool().这样,我们在app中
请求的一些media相关的服务,在media server进程中就会通过binder线程得知,从而执行相关的任务,完成后,把结果或者执行状态再通过binder返回到app进程中。
以上就是在应用进程中和native进程中,binder线程的大概的启动过程。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: