Android Binder線程

在android系統中,經過binder進行IPC時,服務端老是會起一些Binder線程來響應客戶端的請求。以下面的這個設備上,system_process進程中就能夠看到許多名爲"Binder_X"的線程:java

那這些Binder線程又是如何建立,如何管理的呢?而這些Binder線程自己又有些什麼樣的特色呢?在android的java app進程被建立起來時,它就會去創建一個線程池,來專門處理那些binder IPC事務。在frameworks/base/cmds/app_process/app_main.cpp中咱們能夠看到下面的這兩個方法:android

    virtual void onStarted()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
        AndroidRuntime* ar = AndroidRuntime::getRuntime();
        ar->callMain(mClassName, mClass, mArgC, mArgV);
        IPCThreadState::self()->stopProcess();
    }
    virtual void onZygoteInit()
    {
        // Re-enable tracing now that we're no longer in Zygote.
        atrace_set_tracing_enabled(true);
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

app_main實際上就是android java app的java命令。這裏的代碼老是一個android java app執行控制的重要的樞紐。大致掃一眼這個部分的code,沒錯,就是上面的proc->startThreadPool()這個調用建立的Binder線程池。在android binder的設計中,ProcessState被設計來直接與binder驅動進行通訊。ProcessState類被按照單例模式來設計,以確保這種類的對象能夠保證在進程的全局是惟一的。它的構造函數是private,在代碼中只能經過ProcessState::self()來訪問ProcessState類的對象。咱們順便來看一下ProcessState::self()的實現(frameworks/native/libs/binder/ProcessState.cpp):
app

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

蠻典型的一個C++單例模式的一個實現呢。那在ProcessState::startThreadPool()中又是如何建立線程池的呢?(frameworks/native/libs/binder/ProcessState.cpp)函數

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

這裏會經過一個標記mThreadPoolStarted來代表binder線程線程池是否已經被啓動過。在每次調用這個函數時都會先去檢查這個標記,從而確保即便這個函數被屢次調用,線程池也只會被啓動一次。具體來看啓動線程池的過程:設置mThreadPoolStarted爲true,而後調用spawnPooledThread(true)來建立線程池中的第一個線程,也就是線程池的main線程。oop

那binder線程具體又是什麼呢?能夠看spawnPooledThread()的實現(frameworks/native/libs/binder/ProcessState.cpp)this

String8 ProcessState::makeBinderThreadName() {
    int32_t s = android_atomic_add(1, &mThreadPoolSeq);
    String8 name;
    name.appendFormat("Binder_%X", s);
    return name;
}
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());
    }
}
ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{

能夠看到,所謂的binder線程,不過就是PoolThread而已。在進程全局且惟一的ProcessState對象中,有一個已經建立的binder線程的計數器mThreadPoolSeq,每建立一個新的線程,這個計數器就會加1。在ProcessState::makeBinderThreadName()函數中,會根據當前的binder線程計數器的值來構造新建立的binder線程的線程名"Binder_%X",從而能夠根據線程名來識別各個不一樣的binder線程。atom

PoolThread具體又有些什麼特色呢?這個仍是得看PoolThread的threadLoop()方法實現(frameworks/native/libs/binder/ProcessState.cpp)spa

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

這個卻是簡單的很,就是調用IPCThreadState::self()->joinThreadPool(mIsMain)而已。線程

在android binder設計中,IPCThreadState是一個binder線程的一個抽象,用於管理binder線程的具體執行。這個類被設計爲,其對象在每一個binder線程中惟一。爲了控制這個類的對象的建立,其構造函數也被聲明爲private,而且只能經過IPCThreadState::self()來建立或訪問IPCThreadState類的對象(frameworks/native/libs/binder/IPCThreadState.cpp):設計

static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
static bool gHaveTLS = false;
static pthread_key_t gTLS = 0;
static bool gShutdown = false;
static bool gDisableBackgroundScheduling = false;

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) return NULL;
    
    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {
        if (pthread_key_create(&gTLS, threadDestructor) != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

IPCThreadState::self()函數在第一次被調到時,會先去建立一個線程局部存儲的key,也就是gTLS。隨後則會建立IPCThreadState對象,在IPCThreadState的構造函數中,會把this保存到線程局部存儲gTLS標識的部分去(frameworks/native/libs/binder/IPCThreadState.cpp):

IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mMyThreadId(androidGetTid()),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}

建立好了IPCThreadState對象以後就返回給調用者。所以,這個地方其實是運用了線程局部存儲機制來實現IPCThreadState對象的線程級單例的。

咱們再回到IPCThreadState::joinThreadPool(),來接着看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);
    
    // This thread may have been spawned by a thread that was in the background
    // scheduling group, so first we will make sure it is in the foreground
    // one to avoid performing an initial transaction in the background.
    set_sched_policy(mMyThreadId, SP_FOREGROUND);
        
    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=%p\n",
        (void*)pthread_self(), getpid(), (void*)result);
    
    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
}

在這個函數中,基本上就是執行一個getAndExecuteCommand()的循環。在getAndExecuteCommand()中則會不停的向binder driver拿命令執行,拿命令執行。

Binder線程池中首個線程的建立執行,大體如上所述,在android java app進程一旦被建立,也就緊跟着會被建立。那意思是說,任何一個android Java app都至少有一個Binder線程,而無論它是否有一個service組件並對其餘app提供服務嘍?是的,事實就是這個樣子的。咱們能夠去查看任何一個android java app進程中的線程狀況,都至少有一個以上的Binder線程,甚至是最簡單的HelloWorld app也是這樣的。

所謂的binder線程池,不能是隻有這麼一個線程吧。那Binder線程池中其它的線程又是如何建立的呢?實際上是kernel發命令給某個已經在運行的binder線程來產生新的線程,以下:

    case BR_SPAWN_LOOPER:
        mProcess->spawnPooledThread(false);
        break;

大致的backtrace爲:

IPCThreadState::executeCommand(int32_t cmd) 《= IPCThreadState::getAndExecuteCommand() 《= IPCThreadState::joinThreadPool(bool isMain) 《= PoolThread::threadLoop()。

binder線程真的就只有這兩種建立的方式嗎?所謂的binder線程,不過指的就是執行binder IPC事務處理循環的線程吧。而binder IPC事務處理循環不是被封裝在了IPCThreadState::joinThreadPool()中了嘛。那是否是任何一個線程只要執行了IPCThreadState::self()->joinThreadPool(),就能夠把本身變成一個binder線程了?確實是這樣的。在android系統中,也確實有一些native的service,在設置好執行環境以後,甚至會讓主線程去執行binder IPC事務處理循環從而把主線程變成binder線程。好比在mediaserver中(frameworks/av/media/mediaserver/main_mediaserver.cpp),就會在main()函數的最後來執行IPCThreadState::self()->joinThreadPool():

118    } else {
119        // all other services
120        if (doLog) {
121            prctl(PR_SET_PDEATHSIG, SIGKILL);   // if parent media.log dies before me, kill me also
122            setpgid(0, 0);                      // but if I die first, don't kill my parent
123        }
124        sp<ProcessState> proc(ProcessState::self());
125        sp<IServiceManager> sm = defaultServiceManager();
126        ALOGI("ServiceManager: %p", sm.get());
127        AudioFlinger::instantiate();
128        MediaPlayerService::instantiate();
129        CameraService::instantiate();
130        AudioPolicyService::instantiate();
131        registerExtensions();
132        ProcessState::self()->startThreadPool();
133        IPCThreadState::self()->joinThreadPool();
134    }

binder線程還具備一個特色。那就是binder線程線程池中線程的數量是有一個上限的,咱們能夠看ProcessState.cpp中open_driver()函數的實現:

343static int open_driver()
344{
345    int fd = open("/dev/binder", O_RDWR);
346    if (fd >= 0) {
347        fcntl(fd, F_SETFD, FD_CLOEXEC);
348        int vers;
349        status_t result = ioctl(fd, BINDER_VERSION, &vers);
350        if (result == -1) {
351            ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
352            close(fd);
353            fd = -1;
354        }
355        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
356            ALOGE("Binder driver protocol does not match user space protocol!");
357            close(fd);
358            fd = -1;
359        }
360        size_t maxThreads = 15;
361        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
362        if (result == -1) {
363            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
364        }
365    } else {
366        ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
367    }
368    return fd;
369}

在這個函數中,會經過ioctl命令,告訴binder驅動,只能建立最多15個的binder線程。

Done.

相關文章
相關標籤/搜索