Binder线程池的启动

QuibblerQuibbler 2020-07-12 约 13 分钟 2313 次阅读

Binder线程池的启动

Binder线程池在Android是一个非常重要的技术,访问其它应用ContentProvider的,应用进程和系统服务之间的通信等操作在服务端是运行在Binder线程池中的。Binder线程池是一个比较底层的概念,关于Binder的代码在native层中:

../frameworks/native/libs/binder

接着APP进程的启动(见:APP进程启动流程),在ZygoteInit的zygoteInit(...)方法

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ...
        //启动Binder线程池
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

提到ZygoteInit的nativeZygoteInit()方法,该方法定义是native层的方法:

private static final native void nativeZygoteInit();

进入AOSP的native源码目录找到binder,这里面定义了关于Binder线程池的顶层逻辑实现代码。ZygoteInit的nativeZygoteInit()方法经过JNI映射,调用到app_main.cpp中

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

ProcessState的self()方法返回单例

sp<ProcessState> ProcessState::self()
    {
        Mutex::Autolock _l(gProcessMutex);
        if (gProcess != nullptr) {
            return gProcess;
        }
        gProcess = new ProcessState(kDefaultDriver);
        return gProcess;
    }

在onZygoteInit()方法中调用startThreadPool()方法

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

再调用spawnPooledThread(bool )方法

void ProcessState::spawnPooledThread(bool isMain)
    {
        if (mThreadPoolStarted) {
            String8 name = makeBinderThreadName();
            ALOGV("Spawning new pooled thread, name=%s\n", name.string());
            sp<Thread> t = new PoolThread(isMain);
            t->run(name.string());
        }
    }

PoolThread类定义在ProcessState类中,继承自Thread线程

class PoolThread : public Thread
    {
    public:
        explicit PoolThread(bool isMain)
            : mIsMain(isMain)
        {
        }
        
    protected:
        virtual bool threadLoop()
        {
            IPCThreadState::self()->joinThreadPool(mIsMain);
            return false;
        }
        
        const bool mIsMain;
    };

PoolThread的run(...)方法执行:先获取IPCThreadState单例,借助IPCThreadState::self()

IPCThreadState* IPCThreadState::self()
    {
        if (gHaveTLS) {
    restart:
            const pthread_key_t k = gTLS;
            IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
            if (st) return st;
            return new IPCThreadState;
        }
        if (gShutdown) {
            ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
            return nullptr;
        }
        pthread_mutex_lock(&gTLSMutex);
        if (!gHaveTLS) {
            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 nullptr;
            }
            gHaveTLS = true;
        }
        pthread_mutex_unlock(&gTLSMutex);
        goto restart;
    }

现在已经看不太懂C++语法(╥╯^╰╥) ,仿佛看到了goto跳转。该方法返回的IPCThreadState单实例

最后,调用joinThreadPool(bool isMain)方法将当前构造的Binder线程池注册到Binder驱动中。

void IPCThreadState::joinThreadPool(bool isMain)
    {
        LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
        mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
        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) {
                ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                      mProcess->mDriverFD, result);
                abort();
            }
            // 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);
        talkWithDriver(false);
    }

创建的线程加入到Binder线程池中,应用程序启动之后就支持使用这个Binder线程进行进程间通信,至于Binder是如何实现进程间通信的,就无需再往下“刨”了,不求甚解。

学习资料:

        Android进阶解密 > 第三章 Binder线程池启动过程

        进程的Binder线程池工作过程

Android binder机制---ProcessState和线程池

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w