Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Binder進程間通信---注冊Service組件---啟動Binder線程池

Android Binder進程間通信---注冊Service組件---啟動Binder線程池

編輯:關於Android編程

本文參考《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進程間通信---注冊Service組件---發送和處理BC_REPLY返回協議http://blog.csdn.net/jltxgcy/article/details/26339313,執行完waitForResponse函數,參考Android Binder進程間通信---注冊Service組件---Client發送BC_TRANSACTION。應該返回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 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. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved