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;
}
总结
- 打开binder驱动。
- 映射进程内存,分配缓冲区。
- 注册binder线程
- 进入binder loop。
参考
- Android系统源代码情景分析
- 慕课网