启动Binder机制

369 阅读2分钟

Binder线程池的启动过程时序图

Binder启动过程分析

frameworks/base/core/jni/AndroidRuntime.cpp

1 static AndroidRuntime* gCurRuntime = NULL;
2 ......
3 
4 static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
5 {
6     gCurRuntime->onZygoteInit();
7 }

frameworks/base/cmds/app_process/app_main.cpp

virtual void onZygoteInit(){
    //拿到当前的ProcessState
    sp<ProcessState> proc = ProcessState::self();
    //启动线程池
    proc->startThreadPool();
}
 
//这是典型的单例模式,就像java的getInstance
sp<ProcessState> ProcessState::self(){
    if(gProcess != NULL){
        return gProcess;
    }
    gProcess = new ProcessState;
    return gProcess;
}
 
//再看ProcessState的构造函数
ProcessState::ProcessState()
//这里有一个成员变量叫mDriverFD,它是通过open_driver返回的,open_Driver做了什么?
//open("/dev/biner",O_RDWR);所以ProcessState打开的binder驱动
    :mDriverFD(open_driver()),...{
        if(mDriverFD >= 0){
            //DriverFB有效,就把它映射到当前进程的内存空间,
            mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, ..., mDriverFD, 0);
        }
}

frameworks/base/libs/binder/ProcessState.cpp


void ProcessState::startThreadPool(){
    //布尔变量做防御,防止里面调2次
    if(!mThreadPoolStarted){
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}
 
void ProcessState::spawnPooledThread(bool isMain){
    if(mTheadPoolStarted){
        //new一个PoolThread然后run起来,
        //原来线程池里就这么一个线程,名不副实
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string());
    }
}
 
//再看看poolThread
//继承了thread类,
class PoolThread:public Thread{
    //调用threadLoop函数
    virtual bool threadLoop(){
        //这里出现了一个IPCTthreadState,它也是单例
        //但是是线程里面的单例,而不是进程里面的单例
        //joinThreadPool将当前线程注册到Binder驱动程序中去成为一个Binder线程,以便Binder驱动程序可以分发进程间通信请求给它处理。
        IPCThreadState::self()->joinThreadPool(mlsMain);
        return false;
    }
}
 
void IPCThreadSttate::joinThreadPool(bool isMain){
    //IPCTHreadState里面有两个parce,一个是mIn,一个mOut,
    //如果有什么数据要写到Binder驱动,就写到mOut,
    //如果有数据返回回来,数据就放在mIn里面
    //根据参数isMain的值不同,相应地将一个BC_ENTER_LOOPER或者BC_REGISTER_LOOPER命令协议写入到IPCThreadState类内部的命令协议缓冲区mOut中,以便接下来可以调用成员函数talkWithDriver将它里面的BC_ENTER_LOOPER或者BC_REGISTER_LOOPER命令协议发送给Binder驱动程序,从而完成注册Binder线程的过程。 
    mOut.writeInt32(isMain?BC_ENTER_LOOPER:BC_REGISTER_LOOPER);
    do{
        //循环,不会退出,
        //getAndExecuteCommand是核心函数
        result = getAndExecuteCommand();
        ...
    }while(result != -ECONNREFUSED && result != -EBADF);
}
 
status_t IPCThreadState::getAndExecuteCommand(){
    //可以能驱动写,也可能从驱动读,
    //对于binder线程,一般是等待从binder驱动发过来的binder transact请求,读完再回复请求
    talkWithDriver();
    
    //读cmd并且处理cmd,所以这里是根据binder发过来的指令执行不同的操作。
    cmd = mln.readInt32();
    executeCommand(cmd);
    
    return result;
}

总结

  1. 打开binder驱动。
  2. 映射进程内存,分配缓冲区。
  3. 注册binder线程
  4. 进入binder loop。

参考

  • Android系统源代码情景分析
  • 慕课网