??????? 在Android中ProcessState是客戶端和服務端公共的部分,作為Binder通信的基礎,ProcessState是一個singleton類,每個
進程只有一個對象,這個對象負責打開Binder驅動,建立線程池,讓其進程里面的所有線程都能通過Binder通信。
與之相關的是IPCThreadState,每個線程都有一個IPCThreadState實例登記在Linux線程的上下文附屬數據中,主要負責
Binder的讀取,寫入和請求處理框架。IPCThreadState在構造的時候獲取進程的ProcessState并記錄在自己的成員變量
mProcess中,通過mProcess可以獲得Binder的句柄。
~~~
frameworks/base/include/binder/ProcessState.h
class ProcessState : public virtual RefBase
{
public:
static sp<ProcessState> self(); // 單例模式,獲取實例
void setContextObject(const sp<IBinder>& object);
sp<IBinder> getContextObject(const sp<IBinder>& caller);
void setContextObject(const sp<IBinder>& object, const String16& name);
sp<IBinder> getContextObject(const String16& name, const sp<IBinder>& caller);
void startThreadePool();
typdef bool (*context_check_func)(const String16& name, const sp<IBinder>& caller, void* userData);
bool isContextManager(void) const;
bool becomeContextManager(context_check_func checkFunc, void* userData);
sp<IBinder> getStrongProxyForHandle(int32_t handle);
wp<IBinder> getWeakProxyForHandle(int32_t handle);
void espungeHandle(int32_t handle, IBinder* binder);
void spawnPooledThread(boot isMain);
private:
friend class IPCThreadState;
ProcessState();
~ProcessState;
ProcessState(const ProcessState& o);
ProcessState& operator=(const ProcessState& o);
struct hdndle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
handle_entry* lookupHandleLocked(int32_t handle);
int mDriverFD; // 打開的binder驅動文件描述符
void* mVMStart;
Vector<handle_entry> mHandleToObject;
bool mManagerContexts;
context_check_func mBinderContextCheckFunc;
void* mBinderContextUserData;
KeyedVector<String16, sp<IBinder> > mContexts; // 映射,服務名字 和 IBinder對應
bool mThreadPoolStarted; // 線程池是否已經創建
volatile int32_t mThreadPoolSeq; // 這個進程中啟動線程個數
};
~~~
**1)獲得ProcessState的實例**
~~~
sp<ProcessState> proc(ProcessState::self());
調用函數:
sp<ProcessState> ProcessState::self()
{
if (gProcess != NULL) return gProcess;
AutoMutext _l(gProcessMutex);
if(gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
進入構造函數:
ProcessState::ProcessState() : mDriverFD(open_driver())
, mVMStart(MAP_FAILED),
, mManagerContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThradPoolStarted(false)
, mThreadPoolSeq(1)
{
}
~~~
這個構造函數里面調用open_driver()打開了/dev/binder設備驅動文件,返回文件描述符。這樣我們就能通過這個mDriverFd
來和binder驅動交互了。
**2)創建線程ProcessState::self()->startThreadPool();**
~~~
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if(!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPoolThread(bool isMain)
{
if (mThreadPoolStarted) {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
sp<Thread> t = new PoolThread(isMain);
t->run(buf);
}
}
~~~
~~~
其實這里就是創建一個線程PoolThread,而PoolThread是一個繼承于Thread的類。所以調用t->run()之后相當于調用
PoolThread類的threadLoop()函數,我們來看看PoolThread類的threadLoop線程函數。
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
// 這里線程函數調用了一次IPCThreadState::self()->joinThreadPool()后就退出了
return false;
}
~~~
**3)IPCThreadState::self()->joinThreadPool();**
我們知道:進程調用spawnPoolThread()創建了一個線程,執行joinThreadPool(),而主線程也是調用這個函數。唯一區別是參數,主線程調用的joinThreadPool(true),創建的線程調用的是jointThreadPool(false)。
下面我們來分析下這個函數,首先我們來看看IPCThreadState這個類
~~~
frameworks/base/include/IPCThreadState.h
class IPCThreadState
{
public:
static IPCThreadState* self();
sp<ProcessState> process();
......
void joinThradPool(bool isMain = true);
status_t transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
void incStrongHandle(int32_t handle);
void decStrongHandle(int32_t handle);
void incWeakHandle(int32_t handle);
void decWeakHandle(int32_t handle);
private:
IPCThraedState();
~IPCThreadState();
status_t sendReplay(const Parcel& reply, uint32_t flags);
status_t waitForResponse(Parcel& reply, status_t *acquireResult = NULL);
status_t talkWithDriver(bool doReceice = true);
status_t writeTransactionData();
status_t executeCommand();
private:
sp<ProcessState> mProcess;
Vector<BBinder> mPendingStrongDerefs;
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
Parcel mIn;
Parcel mOut;
}
上面是IPCThreadState類常用的幾個函數。
IPCThreadState* IPCThreadState::self()
{
if(gHaveTLS) { // 第一次進來肯定為false
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if(st) return st;
return new IPCThreadState; // new 一個IPCThreadState對象
}
if(gShutdown) return NULL;
pthread_mutex_lock(&gTLSMutex);
if(!gHaveTLS) {
// 第一個參數為指向一個鍵值的指針,第二個參數指明一個destructor函數,當線程結束時調用
if(phread_key_create(&gTLS, threadDestructor) != 0) {
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
~~~
下面來說明下線程中特有的線程存儲:Thread Specific Data.
在多線程中,所有線程共享程序中變量,如果每一個線程都希望單獨擁有它,就需要線程存儲了。即一個變量表面看起來是
全局變量,所有線程都可以使用它,它的值在每一個線程都是單獨存儲的。
**用法:**
???? ?1)創建一個類型為pthread_key_t 類型變量
???? ?2)pthread_key_create()創建改變量,第二個參數表上一個清理函數,用來在線程釋放該線程存儲的時候調用。
????? 3)當線程中需要存儲特殊值的時候,可以用pthread_setspecific(),第一個參數為pthread_key_t 變量,第二個參數為void* 變量,可以存儲任何類型的值。
???? ?4)當需要取出存儲值的時候,調用pthread_getspecific(),返回void*類型變量值。
好了我們現在知道pthread_key_t是干什么用的了?既然代碼中有pthread_getspecific()獲取IPCThreadState*對象的函數那么肯定有設置這個變量值的地方?我們找到IPCThreadState的構造函數:
~~~
IPCThreadState:IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(androidGetTid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
pthread_setspecific(gTLS, this); // 設置為當前this 指針
clearCaller();
mIn.setDataCapacity(256); // 這里mIn 和 mOut分別表示Binder輸入輸出的變量,我們后面分析
mOut.setDataCapacity(256);
}
~~~
~~~
最后進入IPCThreadState::joinThreadPool(bool isMain)
void IPCThreadState::joinThreadPool(bool isMain) // 默認為true
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
do {
int32_t cmd;
if(mIn.dataPosition() >= mIn.dataSize()){
size_t numPending = mPendingWeakDerefs.size();
if(numPending > 0) {
for(size_t i = 0; i < numPending; i++) {
RefBase::weakref_type* refs = mPendingWeakDerefs[i];
refs->decWeak(mProcess.get);
}
mPendingWeakDerefs.clear();
}
numPending = mPendingStrongDerefs.size();
if(numPending > 0) {
for(sizt_t i = 0; i < numPending; i++) {
BBinder* obj = mPendingStrongDerefs[i];
obj->decStrong(mProcess.get);
}
mPendingStrongDerefs.clear();
}
}
// 讀取下一個command進行處理
result = talkWithDriver();// 來等待Client的請求
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)
break;
} while(result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
~~~
這里的talkWithDriver()里面之際調用的是ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)從/dev/binder讀取Client端發過來的請求,然后調用executeCommand處理
~~~
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch(cmd) {
case BR_TRANSACTION:
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
....
Parcel reply;
if(tr.target.ptr) {
sp<BBinder> b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
}
....
break;
}
}
最后又調用到BBinder 的transact()函數里面去了。
status_t BBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags )
{
data.setDataPosition(0);
switch(code)
{
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
return err;
}
~~~
到這里IPCThreadState類的流程就大概清楚了,線程調用joinThreadPool()從/dev/binder讀取客戶端的請求,然后調用
BBinder::transact()處理。那么這個BBinder是怎么來的呢?
上面代碼中:sp<BBinder> b((BBinder*)tr.cookie)說明這個BBinder指針是從Binder驅動中獲取到,肯定是客戶端發送過來的,那么它的實際類型又是什么呢?而BBinder調用的onTransact()函數只是一個虛函數,肯定由它的子類來實
現,那我們服務端又怎么找到這個BBinder的實際類型呢?
這些內容我們下一節通過MediaPlayer這個具體示例分析。
- 前言
- Android開發之serviceManager分析
- Android啟動之init.c文件main函數分析
- Android開發之ProcessState和IPCThreadState類分析
- Android開發之MediaPlayerService服務詳解(一)
- Android系統五大布局詳解Layout
- Android四大組件之Content Provider
- Android四大組件之Service
- Android四大組件之BroadcastReceiver
- Android系統中的消息處理Looper、Handler、Message
- Android EditText/TextView使用SpannableString顯示復合文本
- Android關鍵資源詳解
- Android常用適配器分析(如何制作簡易Launcher)
- Android常用列表控件