FregServer进程,启动Binder线程池,睡眠等待在proc->wait

时间:2022-08-28 21:57:48

本文参考《Android系统源代码情景分析》,作者罗升阳

一、测试代码:

       ~/Android/external/binder/server

        ----FregServer.cpp

        ~/Android/external/binder/common

        ----IFregService.cpp

        ----IFregService.h

       ~/Android/external/binder/client

       ----FregClient.cpp


       Binder库(libbinder)代码:

       ~/Android/frameworks/base/libs/binder

       ----BpBinder.cpp

       ----Parcel.cpp

       ----ProcessState.cpp

       ----Binder.cpp

       ----IInterface.cpp

       ----IPCThreadState.cpp

       ----IServiceManager.cpp

       ----Static.cpp

       ~/Android/frameworks/base/include/binder

       ----Binder.h

       ----BpBinder.h

       ----IInterface.h

       ----IPCThreadState.h

       ----IServiceManager.h

       ----IBinder.h

       ----Parcel.h

       ----ProcessState.h


        驱动层代码:

       ~/Android//kernel/goldfish/drivers/staging/android

       ----binder.c

       ----binder.h


二、源码分析

      继续上一篇Android Binder进程间通信---FregServer进程,处理BC_REPLY,返回BR_REPLYhttp://blog.csdn.net/jltxgcy/article/details/26339313,执行完waitForResponse函数,参考Android Binder进程间通信---FregServer进程,发送BC_TRANSACTION,睡眠等待http://blog.csdn.net/jltxgcy/article/details/26076149。应该返回IPCThreadState类的transact方法,再返回BpBinder类的transact函数,最后返回BpServiceManager类addService函数。最后再返回FregService类的main函数,实现如下:

       ~/Android/external/binder/server

        ----FregServer.cpp

int main(int argc, char** argv)
{
	FregService::instantiate();

	ProcessState::self()->startThreadPool();//启动一个Binder线程池
	IPCThreadState::self()->joinThreadPool();//主线程加入线程池

	return 0;
}
      首先当前进程的ProcessState对象的成员函数startThreadPool来启动一个Binder线程池,接着继续调用当前线程的IPCThreadState对象的成员函数joinThreadPool,将当前线程加入到前面所启动的Binder线程池中去等待和处理来自Client进程的进程间通信请求。

      下面我们就分析ProcessState类的成员函数startThreadPool的实现,在分析过程中,同时也会分析IPCThreadState类的成员函数joinThreadPool的实现。

       ProcessState类的成员函数startThreadPool的实现如下:

       ~/Android/frameworks/base/libs/binder

       ----ProcessState.cpp

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {//默认值为false
        mThreadPoolStarted = true;//防止它的成员函数spawnPooledThread被重复调用来启动Binder线程池
        spawnPooledThread(true);
    }
}
     当前进程的ProcessState对象的成员变量mThreadPoolStarted被初始化为false,当它将一个Binder线程池启动起来之后,就会将内部的成员变量mThreadPoolStarted的值设置为true,防止它的成员函数spawnPooledThread被重复调用来启动Binder线程池。spawnPooledThread函数实现如下:

       ~/Android/frameworks/base/libs/binder

       ----ProcessState.cpp

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        int32_t s = android_atomic_add(1, &mThreadPoolSeq);
        char buf[32];
        sprintf(buf, "Binder Thread #%d", s);
        LOGV("Spawning new pooled thread, name=%s\n", buf);
        sp<Thread> t = new PoolThread(isMain);//isMain为true
        t->run(buf);//启动一个新的线程
    }
}
       创建了一个PoolThread对象t,调用它的成员函数run来启动一个新的线程。

       PoolThread类继承了线程类Thread,并且重写了它的线程入口成员函数threadLoop,因此当一个PoolThread对象t所对应的线程启动起来之后,它的成员函数threadLoop就会被调用。实现如下:

       ~/Android/frameworks/base/libs/binder

       ----ProcessState.cpp

class PoolThread : public Thread
{
public:
    PoolThread(bool isMain)
        : mIsMain(isMain)//isMain为true
    {
    }
    
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);//isMain为true
        return false;
    }
    
    const bool mIsMain;
};
      和主线程一样调用了IPCThreadState类的成员函数joinThreadPool。实现如下:

       ~/Android/frameworks/base/libs/binder

       ----IPCThreadState.cpp

void IPCThreadState::joinThreadPool(bool isMain)//默认值为true
{
    .........

    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);//isMain为true,BC_ENTER_LOOPER
    
    ........
        
    status_t result;
    do {
        int32_t cmd;
        
        .......
        result = talkWithDriver();//将自己注册到Binder线程池中,一个无线循环中不断等待进程间通信请求
        if (result >= NO_ERROR) {
            size_t IN = mIn.dataAvail();
            if (IN < sizeof(int32_t)) continue;
            cmd = mIn.readInt32();
            ........


            result = executeCommand(cmd);//处理进程间通信请求
        }
        
       .........
        if(result == TIMED_OUT && !isMain) {//一直为false,因为isMain为true
            break;
        }
    } while (result != -ECONNREFUSED && result != -EBADF);

    ........
    
    mOut.writeInt32(BC_EXIT_LOOPER);//退出Binder线程池
    talkWithDriver(false);
}
       参数isMain是一个默认参数,它的默认值为true。从前面的调用过程可以知道,无论是FregServer进程的主线程,还是FregServer进程刚才所创建的线程,它们都是主动(isMain为true)请求加入到Binder线程池的,即它们都不是由于Binder驱动程序请求创建而加入到Binder线程池的。

       一个Binder线程的生命周期可以划分为三个阶段:

       第一阶段是将自己注册到Binder线程池中;

       第二阶段是一个无线循环中不断等待和处理进程间通信请求;
       第三阶段是退出Binder线程池。

       

       最后执行完的结果是FregServer有两个线程,睡眠等待进程间通信数据的到来。