5.3.4 Server进程开启线程池
在mediaserver进程中通过以下代码开启线程池:
ProcessState:self()->startThreadPool();
IPCThreadState:self()->joinThreadPool();
这里又涉及ProcessState方法和IPCThreadState方法,因此很可能需要Binder通信。
1.startThreadPool
ProcessState的startThreadPool方法代码如下:
void ProcessState:startThreadPool()
{
AutoMutex_l(mLock);
if(!mThreadPoolStarted){
mThreadPoolStarted=true;//线程池启动标记
spawnPooledThread(true);
}
}
startThreadPool首先将全局变量mThreadPoolStarted赋值为true,然后调用spawnPooledThread,其代码如下:
void ProcessState:spawnPooledThread(bool isMain)
{
if(mThreadPoolStarted){//已经设为true
int32_t s=android_atomic_add(1,&mThreadPoolSeq);
char buf[16];
//创建PoolThread,并调用其run方法
sp<Thread>t=new PoolThread(isMain);
t->run(buf);
}
}
PoolThread是Thread的子类,创建一个PoolThread相当于创建一个新的线程,然后执行新线程的run方法运行该线程,其代码如下:
class PoolThread:public Thread
{
public:
PoolThread(bool isMain)
:mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState:self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;//内部保存了传入的isMain参数,此时为true
};
Thread类定义于frameworks/native/libs/utils/Threads.cpp,执行其run方法时,会调用其内部createThreadEtc方法进而执行线程函数_threadLoop,最终执行Thread.threadLoop函数。因此ProcessState的startThreadPool方法的作用是创建一个新线程,并调用IPCThreadState的joinThreadPool将新线程加入到线程池中。
2.joinThreadPool
最后,在mediaserver的主线程中调用IPCThreadState的joinThreadPool方法将主线程也加入到线程池中。joinThreadPool代码如下:
void IPCThreadState:joinThreadPool(bool isMain)
{
/根据isMain选择BC_ENTER_LOOPER存入输出缓冲区mOut/
mOut.writeInt32(isMain?BC_ENTER_LOOPER:BC_REGISTER_LOOPER);
set_sched_policy(mMyThreadId, SP_FOREGROUND);
status_t result;
do{
int32_t cmd;
if(mIn.dataPosition()>=mIn.dataSize()){
……
}
//发起一次Binder通信
result=talkWithDriver();
if(result>=NO_ERROR){
size_t IN=mIn.dataAvail();//获取Binder驱动返回的BR指令
if(IN<sizeof(int32_t))continue;
cmd=mIn.readInt32();
result=executeCommand(cmd);//处理BR指令
}
set_sched_policy(mMyThreadId, SP_FOREGROUND);
if(result==TIMED_OUT&&!isMain){
break;
}
}while(result!=-ECONNREFUSED&&result!=-EBADF);
//退出线程池时,需要以BC指令通知Binder驱动
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
可见将线程加入线程池,需要通过BC指令通知Binder驱动程序。完成这个过程后,mediaserver中将初始化两个Binder线程来处理客户端请求。