Android binder线程池

8 阅读6分钟

本文主要讲这两行代码

sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();

我们都知道binder跨进程通讯不能在zygote中,因为zygote需要fork出其他进程;不适合多线程开启

  • 从zygote fork出了systemserver进程,
  • 并且zygote进程没有binder的线程池;binder线程池是在systemserver线程中开启的;

看下源码


// \frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        
/* Hardcoded command line to start the system server */
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {

        /* Request to fork the system server process */
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    /* For child process */
    if (pid == 0) {
        //systemserver进程
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }

        zygoteServer.closeServerSocket();
        //systemserver进程中处理
        return handleSystemServerProcess(parsedArgs);
    }

    return null;
}
    
    
    
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        //调用zygoteInit
        return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, 
                                    parsedArgs.remainingArgs, cl);
}
    
    
public static final Runnable zygoteInit(int targetSdkVersion, 
                                String[] argv, ClassLoader classLoader) {

    //调用AndroidRuntime中com_android_internal_os_ZygoteInit_nativeZygoteInit
    ZygoteInit.nativeZygoteInit();
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

//AndroidRuntime中com_android_internal_os_ZygoteInit_nativeZygoteInit
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
	//app_main.cpp 中的onZygoteInit:开启binder线程池
    gCurRuntime->onZygoteInit();
}


// \frameworks\base\cmds\app_process\app_main.cpp
virtual void onZygoteInit()
{
    sp<ProcessState> proc = ProcessState::self();
    ALOGV("App process: starting thread pool.\n");
    proc->startThreadPool();
}

也就是说下面这两行代码就是开启了binder线程池,那么是如何开启binder线程池的,这个博客专门解释一下

sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();

看下\frameworks\native\libs\binder\ProcessState.cpp这个类; 1.先看下self()方法

//单例,并且创建ProcessState时传入"/dev/binder",这个应该是binder驱动的路径
sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState("/dev/binder");
    return gProcess;
}


//ProcessState构造器,语法有点特殊,对于java开发可能有点看不懂,下面简单解释下
ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

题外话,C++语法
class MyClass {

private:
    int a;
    double b;

public:
    MyClass(int x, double y) : a(x), b(y) {
        // 构造函数体
    }
};

// 初始化列表: 后面的 a(x) 和 b(y) 分别初始化成员变量 x赋值给a 和 y赋值给 b。

class MyClass : Base1, Base2 {
private:
    int a;
    double b;
    std::string c;

public:
    MyClass(int x, double y, const std::string& z) :
                Base1(x),
                Base2(y),
                a(x),
                b(y),
                c(z) 
    {
    // 构造函数体

    }

};
//这里Base1(x),表示执行基类Base1的构造器
//a(x) 还是一样把x赋值给a

回到原题:继续分析ProcessState

所以ProcessState得构造器就是给成员变量赋值

注意:mDriverFD(open_driver(driver))这里赋值的时候执行的open_driver()

并且调用的mmap,映射到虚拟内存,映射的内存大小也是众所周知

mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)

binder虚拟内存映射大小:1M - 8k

ok,第一行构造器分析完了,看第二行

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}


void ProcessState::spawnPooledThread(bool isMain)
{
    //很明显上面startThreadPool方法中: mThreadPoolStarted 为true
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        //这里创建了PoolThread对象,这个类就是ProcessState.cpp这个文件中,如下
        sp<Thread> t = new PoolThread(isMain);
        //执行run后,就会执行PoolThread的threadLoop方法
        t->run(name.string());
    }
}


//PoolThread类
class PoolThread : public Thread
{
public:
//isMain = true
    explicit PoolThread(bool isMain)
        : mIsMain(isMain)
    {
    }
    
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        // threadLoop返回false,说明这里只执行一次,就退出
        return false;
    }
    
    const bool mIsMain;
};

我们知道继承自PoolThread继承Thread,对于这个多线程类,之前博客中有解释

Android native层多线程类Thread

现在也就是会执行IPCThreadState 的方法,并且调用joinThreadPool()

接着看IPCThreadState类

// \frameworks\native\libs\binder\IPCThreadState.cpp
IPCThreadState* IPCThreadState::self()
{
//gHaveTLS 默认为false

    if (gHaveTLS) {
    //3. goto restart会执行到这里
restart:
        // 4. gTLS是创建线程时,获取的线程信息
        const pthread_key_t k = gTLS;
        //5. 这里根据创建线程的gTLS信息,创建一个IPCThreadState对象
        // 正常情况下st为null,因为获取不到值
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        //6. 没创建成功,自己new一个IPCThreadState;接着就可以看IPCThreadState构造器了
        return new IPCThreadState;
    }

    if (gShutdown) {
        ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
        return NULL;
    }

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {
    //1.先走这里,会创建一个线程
    //pthread_key_create有两个参数,
    //第一个是创建一个pthread_key_t结构体;第二个参数是线程结束时执行的函数
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                    strerror(key_create_value));
            return NULL;
        }
        //2.创建gTLS后,gHaveTLS赋值为true
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex); 
    goto restart;
}

IPCThreadState构造器
IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
    //这里设置了值也就是IPCThreadState对象,上面方法中的第5步才能获取到值
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}

从IPCThreadState::self()方法的第5步很明显可以知道

  • 当前线程没有IPCThreadState对象的时候,才会去new一个IPCThreadState;
  • 有IPCThreadState对象的时候,直接从pthread_getspecific获取
  • 所以,一个线程只有一个IPCThreadState对象。

接着再看joinThreadPool方法

void IPCThreadState::joinThreadPool(bool isMain)
{


    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    status_t result;
    do {
        //数据处理,
        processPendingDerefs();
        // 主要调用talkWithDriver()和executeCommand(cmd);
        result = getAndExecuteCommand();

        if(result == TIMED_OUT && !isMain) {
            break;
        }
    } while (result != -ECONNREFUSED && result != -EBADF);
    

    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
}



这个方法主要就是调用了talkWithDriver()和executeCommand(cmd);
status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;

    result = talkWithDriver();
    if (result >= NO_ERROR) {
        size_t IN = mIn.dataAvail();
        if (IN < sizeof(int32_t)) return result;
        //cmd是mIn数据读取的int值,mIn流的前32位
        cmd = mIn.readInt32();


        pthread_mutex_lock(&mProcess->mThreadCountLock);
        //mProcess就是上面的ProcessState ;  该进程可运行线程数+1
        mProcess->mExecutingThreadsCount++;
        if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&
                mProcess->mStarvationStartTimeMs == 0) {
            mProcess->mStarvationStartTimeMs = uptimeMillis();
        }
        pthread_mutex_unlock(&mProcess->mThreadCountLock);

        result = executeCommand(cmd);

        pthread_mutex_lock(&mProcess->mThreadCountLock);
        mProcess->mExecutingThreadsCount--;
        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
                mProcess->mStarvationStartTimeMs != 0) {

            mProcess->mStarvationStartTimeMs = 0;
        }
        pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
        pthread_mutex_unlock(&mProcess->mThreadCountLock);
    }

    return result;
}

OK,看下talkWithDriver

//frameworks\native\libs\binder\include\binder\IPCThreadState.h
// 头文件中这样声明talkWithDriver方法,直接调用talkWithDriver(); 就是doReceive=true
    status_t            talkWithDriver(bool doReceive=true);

talkWithDriver从名字就可以看出是跟驱动进行联系,也就是和binder驱动通讯,开始跨进程通讯

方法逻辑如下,

status_t IPCThreadState::talkWithDriver(bool doReceive)
{

    //和Binder驱动通信的结构体
    binder_write_read bwr;

    // Is the read buffer empty?
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();

    // We don't want to write anything if we are still reading
    // from data left in the input buffer and the caller
    // has requested to read the next data.
    //上面的翻译:如果我们正从输入流读取数据,我们就不会去写任何数据。并且调用者请求读取下一个数据
    //意思就是needRead=true时,是写数据,
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

    bwr.write_size = outAvail;
    bwr.write_buffer = (uintptr_t)mOut.data();

    // This is what we'll read.
    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (uintptr_t)mIn.data();
    } else {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }


    // Return immediately if there is nothing to do.
    if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;

    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    status_t err;
    do {

#if defined(__ANDROID__)
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif

    } while (err == -EINTR);

    if (err >= NO_ERROR) {
        if (bwr.write_consumed > 0) {
            if (bwr.write_consumed < mOut.dataSize())
                mOut.remove(0, bwr.write_consumed);
            else
                mOut.setDataSize(0);
        }
        if (bwr.read_consumed > 0) {
            mIn.setDataSize(bwr.read_consumed);
            mIn.setDataPosition(0);
        }
        IF_LOG_COMMANDS() {
            TextOutput::Bundle _b(alog);
            alog << "Remaining data size: " << mOut.dataSize() << endl;
            alog << "Received commands from driver: " << indent;
            const void* cmds = mIn.data();
            const void* end = mIn.data() + mIn.dataSize();
            alog << HexDump(cmds, mIn.dataSize()) << endl;
            while (cmds < end) cmds = printReturnCommand(alog, cmds);
            alog << dedent;
        }
        return NO_ERROR;
    }

    return err;
}

总结

  • ProcessState的startThreadPool也就是在当前进程中,开启一个线程与binder驱动通讯,然后进程跨进程通讯