標籤:android style blog class c code
本文參考《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<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有兩個線程,睡眠等待處理序間通訊資料的到來。