崇信門(mén)戶網(wǎng)個(gè)人留言seo技術(shù)交流
文章目錄
- 一個(gè)Binder的前生今世 (二):Binder進(jìn)程和線程的創(chuàng)建
- binder在進(jìn)程中的啟動(dòng)
- 小結(jié)
- 注釋
一個(gè)Binder的前生今世 (二):Binder進(jìn)程和線程的創(chuàng)建
前篇文章一個(gè)Binder的前生今世 (一):Service的創(chuàng)建 講了一個(gè)Service是如何創(chuàng)建以及如何與客戶端建立聯(lián)系的。講解中涉及到了兩個(gè)類 ProcessState 和 IPCThreadState ,當(dāng)時(shí)沒(méi)有詳細(xì)介紹這兩個(gè)類是怎么來(lái)的,只是介紹了它們?cè)贐inder客戶端和服務(wù)端傳遞的作用。這篇文章我們就來(lái)深入了解下這兩個(gè)類以及和binder的關(guān)系??梢哉f(shuō)這兩個(gè)類整個(gè)串聯(lián)起了Binder驅(qū)動(dòng)和Binder應(yīng)用的聯(lián)系,在Binder的架構(gòu)實(shí)現(xiàn)中屬于中流砥柱的作用。
binder在進(jìn)程中的啟動(dòng)
首先要明確一個(gè)概念: 一個(gè)進(jìn)程中對(duì)應(yīng)一個(gè)Binder進(jìn)程(也就是后文說(shuō)的ProcessState)用來(lái)管理與Binder驅(qū)動(dòng)的通訊和Binder對(duì)應(yīng)的應(yīng)用線程(后文說(shuō)的IPCThreadState)。
要說(shuō)明Binder在進(jìn)程中如何啟動(dòng),我們就需要先了解一個(gè)android的應(yīng)用是如何創(chuàng)建起來(lái)的。當(dāng)然我們這篇文章不介紹Android應(yīng)用是如何創(chuàng)建的,不了解的可以網(wǎng)上查看其他的資料,很多,我也會(huì)另寫(xiě)文章記錄。
Android的應(yīng)用都會(huì)通過(guò)app_main.cpp來(lái)創(chuàng)建,慣例,我們先來(lái)明確用到的類的路徑:
app_main.cpp : Android/frameworks/base/cmds/app_process/app_main.cpp
IPCThreadState : Android/frameworks/native/libs/binder/IPCThreadState.cpp
ProcessState : Android/frameworks/native/libs/binder/ProcessState.cpp
好,我們了解到,Android應(yīng)用的啟動(dòng)都會(huì)走到app_main.cpp中的AppRuntime類的onZygoteInit函數(shù):
virtual void onZygoteInit(){sp<ProcessState> proc = ProcessState::self();ALOGV("App process: starting thread pool.\n");proc->startThreadPool();}
好,這里我們今天的第一個(gè)主角類登場(chǎng)了:ProcessState。先來(lái)了解下這個(gè)類。
這個(gè)類和IPCthreadState在Android的Binder架構(gòu)體系中啟動(dòng)連接應(yīng)用層和驅(qū)動(dòng)層的作用,應(yīng)用和驅(qū)動(dòng)層打交道的所有接口調(diào)用都是在這兩個(gè)類中的。
所以,每當(dāng)一個(gè)應(yīng)用初始化的時(shí)候,都會(huì)調(diào)用到這里,那我們就接著往下看這個(gè)ProcessState是如何初始化的:
sp<ProcessState> ProcessState::self()
{Mutex::Autolock _l(gProcessMutex);if (gProcess != nullptr) {return gProcess;}gProcess = new ProcessState(kDefaultDriver);return gProcess;
}
這個(gè)self函數(shù)就是一個(gè)單例模式,創(chuàng)建ProcessState:
ProcessState::ProcessState(const char *driver): mDriverName(String8(driver)), mDriverFD(open_driver(driver)), mVMStart(MAP_FAILED), mThreadCountLock(PTHREAD_MUTEX_INITIALIZER), mThreadCountDecrement(PTHREAD_COND_INITIALIZER), mExecutingThreadsCount(0), mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mStarvationStartTimeMs(0), mBinderContextCheckFunc(nullptr), mBinderContextUserData(nullptr), mThreadPoolStarted(false), mThreadPoolSeq(1), mCallRestriction(CallRestriction::NONE)
{// TODO(b/139016109): enforce in build system
#if defined(__ANDROID_APEX__)LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
#endifif (mDriverFD >= 0) {// mmap the binder, providing a chunk of virtual address space to receive transactions.mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);if (mVMStart == MAP_FAILED) {// *sigh*ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());close(mDriverFD);mDriverFD = -1;mDriverName.clear();}}#ifdef __ANDROID__LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver);
#endif
}
這里可以大概看出這個(gè)類是管理一個(gè)線程池的作用,另外還有管理binder驅(qū)動(dòng),我們可以看到第3行open_driver ,這里就是打開(kāi)了Bidner驅(qū)動(dòng):
static int open_driver(const char *driver)
{int fd = open(driver, O_RDWR | O_CLOEXEC);if (fd >= 0) {int vers = 0;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)! ioctl() return value: %d",vers, BINDER_CURRENT_PROTOCOL_VERSION, result);close(fd);fd = -1;}size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;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 '%s' failed: %s\n", driver, strerror(errno));}return fd;
}
這里除了open驅(qū)動(dòng)外,還設(shè)置了最大線程數(shù),這里DEFAULT_MAX_BINDER_THREADS為15:
#define DEFAULT_MAX_BINDER_THREADS 15
然后,我們?cè)诨剡^(guò)頭繼續(xù)看ProcessState構(gòu)造函數(shù),接著初始化了一個(gè)鎖mThreadCountLock 1和 一個(gè)條件變量 mThreadCountDecrement 2,最后初始花了內(nèi)存映射:
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
這里可以看到一個(gè)進(jìn)程的mVMStart 內(nèi)存映射大小為:
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
好了,到這里ProcessState的初始化就完成了,它是一個(gè)線程池,管理進(jìn)程中所有的Binder線程,它還負(fù)責(zé)進(jìn)程的Binder驅(qū)動(dòng)打開(kāi)和初始化操作,然后就是開(kāi)啟了與Binder驅(qū)動(dòng)的內(nèi)存映射。
我們接著來(lái)看proc->startThreadPool():
void ProcessState::startThreadPool()
{AutoMutex _l(mLock);if (!mThreadPoolStarted) {mThreadPoolStarted = true;spawnPooledThread(true);}
}
從名字可以看出這個(gè)方法的作用就是啟動(dòng)線程池了。我們繼續(xù)往下跟蹤:
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());}
}
這里的作用就是啟動(dòng)一個(gè)Binder線程了,接著我們就來(lái)到了查看PoolThread是個(gè)什么東東:
class PoolThread : public Thread
{
public:explicit PoolThread(bool isMain): mIsMain(isMain){}protected:virtual bool threadLoop(){IPCThreadState::self(