無論是在Activity啟動(dòng)流程 上篇(Android 10)還是在SystemServer啟動(dòng)流程中都有提到秀睛,在fork出進(jìn)程之后都會(huì)調(diào)用到ZygoteInit.nativeZygoteInit()
也就是啟動(dòng)binder相關(guān)的內(nèi)容。本篇將從這個(gè)函數(shù)開始宙橱,詳細(xì)講講這個(gè)函數(shù)到底是如何開啟binder的。
該函數(shù)在\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
的聲明如下:
private static final native void nativeZygoteInit();
是一個(gè)本地方法呕臂,在\frameworks\base\cmds\app_process\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(DEFAULT_BINDER_VM_SIZE);
return gProcess;
}
這里單例創(chuàng)建了ProcessState
朗儒,傳入了一個(gè)參數(shù)DEFAULT_BINDER_VM_SIZE
拾稳,其定義為:
#define DEFAULT_BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
也就是我們常說的1M-8K吮炕,ProcessState
的構(gòu)造函數(shù)如下:
ProcessState::ProcessState(size_t mmap_size)
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(nullptr)
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mSpawnThreadOnStart(true)
, mThreadPoolSeq(1)
, mMmapSize(mmap_size)
, mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(nullptr, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Mmapping /dev/hwbinder failed: %s\n", strerror(errno));
close(mDriverFD);
mDriverFD = -1;
}
}
else {
ALOGE("Binder driver could not be opened. Terminating.");
}
}
這里初始化了一系列參數(shù),最重要的就是第二個(gè)參數(shù)mDriverFD(open_driver())
访得,其打開了Binder驅(qū)動(dòng)并設(shè)置了一些值:
static int open_driver()
{
//打開binder驅(qū)動(dòng)
int fd = open("/dev/hwbinder", O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
//發(fā)送binder版本
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)!", vers, BINDER_CURRENT_PROTOCOL_VERSION);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
//發(fā)送binder最大線程
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '/dev/hwbinder' failed: %s\n", strerror(errno));
}
return fd;
}
回到上面的onZygoteInit()
函數(shù)龙亲,該函數(shù)調(diào)用完ProcessState::self()
之后調(diào)用了proc->startThreadPool()
陕凹,也就是ProcessState
的startThreadPool
函數(shù):
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
if (mSpawnThreadOnStart) {
//spawn:產(chǎn)卵,產(chǎn)生Binder線程池線程鳄炉,和zygote意思差不多杜耙,還是比較形象的。
spawnPooledThread(true);
}
}
}
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());
}
}
這里首先創(chuàng)建了PoolThread拂盯,之后調(diào)用了其run方法佑女,這個(gè)線程了定義如下,繼承了Thread類谈竿,這個(gè)Thread類是android自己定義的珊豹,路徑為\system\libhwbinder\ProcessState.cpp
,這里可以簡(jiǎn)單的認(rèn)為榕订,其會(huì)運(yùn)行threadLoop
中的內(nèi)容即可,如果想了解更多信息的話蜕便,可以參考Android Framework中的線程Thread及它的threadLoop方法:
class PoolThread : public Thread
{
public:
explicit PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
IPCThreadState::self()
內(nèi)容如下
static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
static bool gHaveTLS = false;
static pthread_key_t gTLS = 0;
static bool gShutdown = 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) {
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;
}
該函數(shù)gHaveTLS
初始值為false
劫恒,所以先直接來到最后一個(gè)if判斷,首先創(chuàng)建一個(gè)ThreadLocal key
轿腺,這里和java的ThreadLocal key
一個(gè)道理两嘴,然后返回到restart
,獲取這個(gè)key
對(duì)應(yīng)的IPCThreadState
如果為null
族壳,則創(chuàng)建一個(gè)憔辫,所以可以明白,每個(gè)線程都有自己的一個(gè)IPCThreadState
仿荆,如果沒有贰您,則創(chuàng)建,當(dāng)然這一點(diǎn)從名字也可以看出來拢操。
回到上面IPCThreadState::self()
調(diào)用完成锦亦,需要調(diào)用IPCThreadState
的joinThreadPool
函數(shù)了:
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
//告訴驅(qū)動(dòng)線程將進(jìn)入循環(huán)
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
mIsLooper = true;
do {
processPendingDerefs();
// now get the next command to be processed, waiting if necessary
//獲取和執(zhí)行命令
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);
mIsLooper = false;
talkWithDriver(false);
}
在這里等待和binder驅(qū)動(dòng)傳送命令過來,并執(zhí)行(詳見getAndExecuteCommand()
令境,不再贅述)杠园,如果不是主線程則退出循環(huán),主線程則繼續(xù)循環(huán)舔庶。至此抛蚁,進(jìn)程中的binder線程就啟動(dòng)完成了。