Android Binder 线程池和线程池工作流程

简介:

每一个进程都有且只有一个processState(单例模式)来描述当前进程在binder通信时binder的状态。且都有一个默认的binder主线程Pool thread来跟底层Binder Driver进行通信,这个线程的主体是一个IPCThreadState对象。关系如下:

Pool Thread的类在ProcessState.cpp中:

Binder 线程池的启动代码走读:

binder线程池的启动是通过调用ProcessState.cpp 的startThreadPool()实现的,主要做了两件事:1.设置了线程池的启动状态 2.调用了spawnPooledThread方法,传入参数为TRUE

1.创建binder线程名

2.创建线程并开启线程。结合上面PoolThread的类看,创建后会执行到threadLoop方法,并传入参数true 调用IPCThreadState的joinThreadPool方法如下:

void IPCThreadState::joinThreadPool(bool isMain)
{
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
//isMain ==TRUE 代表主线程,isMain ==FALSE 代表普通的binder线程
//主线程 BC_ENTER_LOOPER 发送给binder_driver后,binder_driver会确定能否启动线程
//普通binder线程 BC_REGISTER_LOOPER 发送给binder_driver后,binder_driver会确定能否启动线程
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
 
    mIsLooper = true;
    status_t result;
    do {
        processPendingDerefs();
        // now get the next command to be processed, waiting if necessary
        result = getAndExecuteCommand();
 
        if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
            LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                  mProcess->mDriverFD, result);
        }
 
        // Let this thread exit the thread pool if it is no longer
        // needed and it is not the main process thread.
        if(result == TIMED_OUT && !isMain) {
            break;
        }
    } while (result != -ECONNREFUSED && result != -EBADF);
 
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%d\n",
        (void*)pthread_self(), getpid(), result);
 
    mOut.writeInt32(BC_EXIT_LOOPER);
    mIsLooper = false;
    talkWithDriver(false);
}

主线程是在启动binder线程池的时候被创建的,其他线程是binder Driver发送BR_SPAWN_LOOPER 来通知进程创建的。

发送BR_SPAWN_LOOPER的条件如下:

当前进程已经没有可以请求的线程,并且也没有已经ready可用的线程了
当前进程已经开始请求的线程小于最大线程数(每个进程包含主线程一个,其他线程的限额是15个)
当前线程状态不能是BINDER_LOOPER_STATE_REGISTERED,也不能是BINDER_LOOPER_STATE_ENTERED.这两个状态代表此线程的状态已经启动了。不能重复启动

{其中BR_SPAWN_LOOPER 是在BINDER_WORK_TRANSACTION的cmd中被发送出来的,而BINDER_WORK_TRANSACTION是在client发送BC_TRANSACTION或者发送BC_REPLY的时候被调用的

BC_TRANSACTION或发送BC_REPLY 对应两种情景:

BC_TRANSACTION : client进程向 binderDriver发送IPC调用请求的时候

BC_REPLY : server进程收到了binderDriver的IPC调用请求,请求执行完毕后发送返回值时候}
线程池的工作过程:

线程池工作中主要涉及ProcessState,Pool Thread, IPCThreadState 和BpBinder。ProcessState和Pool Thread 、IPCThreadState 都是以单例模式设计的。每个进程中只有一个。

ProcessState 负责创建并管理BpBinder以及Pool Thread,PoolThread的核心是IPCThreadState,这个类里面有两个Parcel对象,分别负责存储从BinderDriver读出来的数据和要往BinderDriver中写入的数据。我们一般使用的各种Manager继承自BpBinder,当我们需要通过IPC调用到server的接口时,会通过BpBinder的transact方法将数据写入到mOut中,然后IPCThreadState 又会通过talkwithDriver将数据发给binderDriver。


Binder通信模型流程图:

滚动至顶部