Binder進程與線程ProcessState以及IPCThreadState


ProcessState以及IPCThreadState

ProcessState是負責打開Binder節點並做mmap映射,IPCThreadState是負責與Binder驅動進行具體的命令交互。

ProcessState

  1. 實現ProcessState的主要關鍵點有以下幾個:
  • 保證同一進程只有一個ProcessState實例,且只有在ProcessState對象建立時才打開Binder設備以及做內存映射
  • 向上層提供IPc服務
  • 與IPCThreadState分工
  1. 首先分析第一個點:
    源碼位置:/frameworks/native/libs/binder/ProcessState.cpp  http://androidxref.com/6.0.1_r10/xref/frameworks/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
    if (gProcess != NULL) return gProcess;

    AutoMutex _l(gProcessMutex);
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}

可以看到,在這里也是先檢查是否存在一個已經實例化的prosessstate,否則創建一個,所以獲取ProcessState對象,需要通過這個self方法。
接下來需要一步步的觀察這個新建的過程當中實現的原理。

  1. 分析構造函數:
ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
        }
#else
        mDriverFD = -1;
#endif
    }
    if (mDriverFD < 0) {
        // Need to run without the driver, starting our own thread pool.
    }
}

可以看到有兩個之前學習的時候了解到了,與Binder驅動緊密相關的方法:
一個是open_driver(),另一個是下面的mmap(),也就是最終打開了Binder結點以及進行了內存塊的映射。

  1. 接下來分析在之前用到的獲取IBinder的對象時的一個方法:getContextObject
    在這個方法中,傳入了一個handel,最終得到了一個BpBinder,而這個BpBinder是Binder在Native層的代理。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}
ProcessState::getStrongProxyForHandle
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
 
    AutoMutex _l(mLock);
 
    handle_entry* e = lookupHandleLocked(handle);
 
    if (e != NULL) {
        ......
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
               ......
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
 
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
 
    return result;
}

ProcessState::lookupHandleLocked

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
    const size_t N=mHandleToObject.size();
    if (N <= (size_t)handle) {
        handle_entry e;
        e.binder = NULL;
        e.refs = NULL;
        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
        if (err < NO_ERROR) return NULL;
    }
    return &mHandleToObject.editItemAt(handle);
}

從這兒看,先調用lookupHandleLocked方法,由於是第一次調用,因此新建一個handle_entry,並返回,而且其binder和refs為NULL
那么getStrongProxyForHandle方法接着往下走,由於binder為NULL,mHandle傳入的是0,因此進入判斷條件中,最后new BpBinder,且參數為0

因此,返回的是new BpBinder(0)

sp<IBinder> b = ProcessState::self()->getContextObject(NULL);

 

 

IPCThreadState

代碼位置:/frameworks/native/libs/binder/IPCThreadState.cpp

http://androidxref.com/6.0.1_r10/xref/frameworks/native/libs/binder/IPCThreadState.cpp

  1. 單實例構造函數:
IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS) { 
    //當執行完第一次之后,再次運行的時候就已經有IPCThreadState實例,只需要獲取就可以使用
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 NULL;
    }

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {       
    //初始的gHaveTLS的值false,所以第一次調用的時候,會執行這里的代碼
    //隨后將gHaveTLS設置為true
        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 NULL;
        }
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

通過上面的方法,就能保證“線程單實例”的目的

  1. 現有的調用分析順序是:
    getService@ServiceManagerProxy-->transact@BinderProxy-->transact@BpBinder-->transact@IPCThreadState
  2. 不管是讀取還是寫入,Binder驅動都只是發揮中間人的作用,真正處理請求的還是Binder Client以及Binder Server雙方。
  3. 真正與Binder打交道的地方時talkWithDriver中的ioctl()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM