在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.