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

本文参考《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有两个线程,睡眠等待进程间通信数据的到来。

### 回答1: 在 Android 系统中,`ProcessState::self()->startThreadPool()` 用于启动 Binder 线程池服务,而 `IPCThreadState::self()->joinThreadPool()` 则是让当前线程加入到 Binder 线程池中。如果一个 HAL service 没有调用 `ProcessState::self()->startThreadPool()`,但是调用了 `IPCThreadState::self()->joinThreadPool()`,那么该 HAL service 就会试图将当前线程加入到不存在的线程池中,这会导致运行时错误。因此,HAL service 在启动时应该始终调用 `ProcessState::self()->startThreadPool()` 来启动 Binder 线程池服务,以便正确地加入到 Binder 线程池中。 ### 回答2: 如果一个 HAL 服务没有调用 `ProcessState::self()->startThreadPool()`,而只调用了 `IPCThreadState::self()->joinThreadPool()`,可能出现以下情况: 1. HAL 服务是在其他进程中运行的:`ProcessState::self()->startThreadPool()` 用于在当前进程启动线程池,而 `IPCThreadState::self()->joinThreadPool()` 用于加入现有的线程池。所以如果一个 HAL 服务运行在其他进程中,它只需要加入已经被其他服务启动线程池即可。 2. HAL 服务是在单线程环境下运行的:在某些情况下,HAL 服务可能是在单线程环境中运行的,不需要多线程支持。此时,并不需要调用 `ProcessState::self()->startThreadPool()` 来启动线程池,只需调用 `IPCThreadState::self()->joinThreadPool()` 即可将服务加入到当前进程的单一线程池中。 总之,只调用 `IPCThreadState::self()->joinThreadPool()` 而不调用 `ProcessState::self()->startThreadPool()` 可能是由于 HAL 服务运行在其他进程中,或者 HAL 服务是在单线程环境中运行的,不需要启动额外的线程池。这种情况下,服务只需加入已存在的线程池即可。 ### 回答3: 在某些情况下,hal service没有调用ProcessState::self()->startThreadPool(),只调用IPCThreadState::self()->joinThreadPool(),主要是因为这个hal service不需要创建自己的线程池。 在Android系统中,HAL(Hardware Abstraction Layer)服务提供了与硬件交互的接口。通常情况下,HAL服务中会涉及到与硬件设备进行通信的操作,比如传感器、摄像头等。为了保证这些HAL服务可以并行运行,Android框架提供了多线程机制。 在HAL服务的实现中,ProcessState::self()->startThreadPool()用于创建一个线程池,并启动多个线程来并行处理来自客户端的请求。而IPCThreadState::self()->joinThreadPool()则会将当前线程加入到线程池中,并等待处理来自客户端的请求。 但是,并不是所有的HAL服务都需要自己的线程池。有些HAL服务可能只需要在调用时等待客户端的请求,而不需要并行处理。对于这种情况,就不需要调用ProcessState::self()->startThreadPool(),只需调用IPCThreadState::self()->joinThreadPool()加入到现有的线程池中即可。 总结来说,如果一个HAL服务没有调用ProcessState::self()->startThreadPool(),只调用了IPCThreadState::self()->joinThreadPool(),那说明这个HAL服务只是简单地等待处理客户端的请求,而不需要额外的线程池来进行并行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值