崇信門戶網(wǎng)個人留言seo技術(shù)交流
文章目錄
- 一個Binder的前生今世 (二):Binder進(jìn)程和線程的創(chuàng)建
- binder在進(jìn)程中的啟動
- 小結(jié)
- 注釋
一個Binder的前生今世 (二):Binder進(jìn)程和線程的創(chuàng)建
前篇文章一個Binder的前生今世 (一):Service的創(chuàng)建 講了一個Service是如何創(chuàng)建以及如何與客戶端建立聯(lián)系的。講解中涉及到了兩個類 ProcessState 和 IPCThreadState ,當(dāng)時沒有詳細(xì)介紹這兩個類是怎么來的,只是介紹了它們在Binder客戶端和服務(wù)端傳遞的作用。這篇文章我們就來深入了解下這兩個類以及和binder的關(guān)系??梢哉f這兩個類整個串聯(lián)起了Binder驅(qū)動和Binder應(yīng)用的聯(lián)系,在Binder的架構(gòu)實現(xiàn)中屬于中流砥柱的作用。
binder在進(jìn)程中的啟動
首先要明確一個概念: 一個進(jìn)程中對應(yīng)一個Binder進(jìn)程(也就是后文說的ProcessState)用來管理與Binder驅(qū)動的通訊和Binder對應(yīng)的應(yīng)用線程(后文說的IPCThreadState)。
要說明Binder在進(jìn)程中如何啟動,我們就需要先了解一個android的應(yīng)用是如何創(chuàng)建起來的。當(dāng)然我們這篇文章不介紹Android應(yīng)用是如何創(chuàng)建的,不了解的可以網(wǎng)上查看其他的資料,很多,我也會另寫文章記錄。
Android的應(yīng)用都會通過app_main.cpp來創(chuàng)建,慣例,我們先來明確用到的類的路徑:
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)用的啟動都會走到app_main.cpp中的AppRuntime類的onZygoteInit函數(shù):
virtual void onZygoteInit(){sp<ProcessState> proc = ProcessState::self();ALOGV("App process: starting thread pool.\n");proc->startThreadPool();}
好,這里我們今天的第一個主角類登場了:ProcessState。先來了解下這個類。
這個類和IPCthreadState在Android的Binder架構(gòu)體系中啟動連接應(yīng)用層和驅(qū)動層的作用,應(yīng)用和驅(qū)動層打交道的所有接口調(diào)用都是在這兩個類中的。
所以,每當(dāng)一個應(yīng)用初始化的時候,都會調(diào)用到這里,那我們就接著往下看這個ProcessState是如何初始化的:
sp<ProcessState> ProcessState::self()
{Mutex::Autolock _l(gProcessMutex);if (gProcess != nullptr) {return gProcess;}gProcess = new ProcessState(kDefaultDriver);return gProcess;
}
這個self函數(shù)就是一個單例模式,創(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
}
這里可以大概看出這個類是管理一個線程池的作用,另外還有管理binder驅(qū)動,我們可以看到第3行open_driver ,這里就是打開了Bidner驅(qū)動:
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ū)動外,還設(shè)置了最大線程數(shù),這里DEFAULT_MAX_BINDER_THREADS為15:
#define DEFAULT_MAX_BINDER_THREADS 15
然后,我們在回過頭繼續(xù)看ProcessState構(gòu)造函數(shù),接著初始化了一個鎖mThreadCountLock 1和 一個條件變量 mThreadCountDecrement 2,最后初始花了內(nèi)存映射:
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
這里可以看到一個進(jìn)程的mVMStart 內(nèi)存映射大小為:
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
好了,到這里ProcessState的初始化就完成了,它是一個線程池,管理進(jìn)程中所有的Binder線程,它還負(fù)責(zé)進(jìn)程的Binder驅(qū)動打開和初始化操作,然后就是開啟了與Binder驅(qū)動的內(nèi)存映射。
我們接著來看proc->startThreadPool():
void ProcessState::startThreadPool()
{AutoMutex _l(mLock);if (!mThreadPoolStarted) {mThreadPoolStarted = true;spawnPooledThread(true);}
}
從名字可以看出這個方法的作用就是啟動線程池了。我們繼續(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());}
}
這里的作用就是啟動一個Binder線程了,接著我們就來到了查看PoolThread是個什么東東:
class PoolThread : public Thread
{
public:explicit PoolThread(bool isMain): mIsMain(isMain){}protected:virtual bool threadLoop(){IPCThreadState::self(