アプリプロセス初期化Binder、ServiceManagerサービスの取得

63982 ワード

データ構造
ProcesState:ユーザー空間でプロセス状態を表し、個々のプロセスはProcessiteオブジェクトだけです.Binderドライバのオープンとスレッドプールの作成を担当しています.
IPCThreadState:ユーザ空間下のスレッドはIPCthreadStateを通じて、binder駆動とコマンドインタラクションを行う.
アプリプロセス起動
Initプロセスはzygoteプロセス、system_を起動しました.serverプロセス、ServiceManagerプロセス、lwkdサービスなど
zygoteは、binder通信を利用していません.socketを利用して情報を受信し、ZygoteInit.main()を実行した後、runSelectLoop()の循環体内に入り、クライアント接続があるとZygoteConnection.runOnce()の方法を実行し、再度呼び出した後、forkに新しいアプリケーションを作成します.
java層Process.start()は、ZygoteConnection.run Once()でプロセスを開始します.
// ZygoteConnection.runOnce
boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    ...
        if (pid == 0) { // fork    ,    pid   0,   
            zygoteServer.closeServerSocket(); //       zygote socket  
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            return true;
        }
}

private void handleChildProc(Arguments parsedArgs,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
        throws Zygote.MethodAndArgsCaller {
    ...
    ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
    parsedArgs.remainingArgs, null /* classLoader */);
}

// ZygoteInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv,
        ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit();
    RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
ZygontenInit
//frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

// frameworks/base/cmds/app_process/App_main.cpp 
virtual void onZygoteInit()
{
    sp<ProcessState> proc = ProcessState::self();
    proc->startThreadPool();
}
プロセスはProcessStateの例しかなく、Processistateオブジェクトが確立された時にのみBinderデバイスを開け、メモリマッピングを行う.
// frameworks/native/libs/binder/ProcessState.cpp
//     
sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState("/dev/binder");
    return gProcess;
}

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)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }
}
open_driver、mmapは分析しましたので、参考にしてください.https://blog.csdn.net/qq_15893929/articale/detail/10395875
startThreadPoolはPool Threadを作成して現在のスレッドを表し、binderスレッドとして登録します.
void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

//          
void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string());
    }
}
PoolThreadはbinderスレッドを表します.
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とbinderドライバのインタラクティブ
void IPCThreadState::joinThreadPool(bool isMain)
{
    //       ,    BC_ENTER_LOOPER,        BC_REGISTER_LOOPER
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    status_t result;
    do {
        processPendingDerefs(); //        
        // now get the next command to be processed, waiting if necessary
        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);

    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
}

status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;
    result = talkWithDriver();
    if (result >= NO_ERROR) {
        ...
        pthread_mutex_unlock(&mProcess->mThreadCountLock);
        result = executeCommand(cmd);
        pthread_mutex_lock(&mProcess->mThreadCountLock);
        ...
    }
    return result;
}

//  binder  ioctl,  bwr,   mOut、mIn
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    binder_write_read bwr;
    …

    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    status_t err;
    do {
       if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
    } while (err == -EINTR);

    if (err >= NO_ERROR) {
        if (bwr.write_consumed > 0) {
            if (bwr.write_consumed < mOut.dataSize())
                mOut.remove(0, bwr.write_consumed);
            else
                mOut.setDataSize(0);
        }
        if (bwr.read_consumed > 0) {
            mIn.setDataSize(bwr.read_consumed);
            mIn.setDataPosition(0);
        }
        return NO_ERROR;
    }

    return err;
}

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR;
    switch ((uint32_t)cmd) {
    case BR_ACQUIRE:
        ...
        break;
    case BR_TRANSACTION:
        ...
        break;
    }
    return result;
}
どのように新しいbinderスレッドを追加しますか?同時に複数のタスクが実行されますので.
IPCThreadStateスレッドでは、ioctlを行い、binderカーネルでbinder_uに入る.ioctl_write_read、bwrが読み出しキャッシュのデータがあれば、
二つのプロセスの間で相互に渡されるデータフォーマットはbinder_である.トランスアクションダタ
プロセスとドライバが互いに転送するデータフォーマットはbinder_です.write_read
それはもっと多くのbinderスレッドが必要かもしれません.binder_を処理します.トランスアクションデータ
static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, binder_uintptr_t binder_buffer, size_t size,binder_size_t *consumed, int non_block)
{ 
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size; 
int ret = 0; 
int wait_for_proc_work;

retry:
    binder_inner_proc_lock(proc);
    //             ,       todo     
    wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
    binder_inner_proc_unlock(proc);
   //           ,        BINDER_LOOPER_STATE_WAITING*/
    thread->looper |= BINDER_LOOPER_STATE_WAITING;
    if (non_block) {
        if (!binder_has_work(thread, wait_for_proc_work))
            ret = -EAGAIN;
    } else {
        // wait_for_proc_work         ,        
        ret = binder_wait_for_work(thread, wait_for_proc_work);
    }
    thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
    if (ret)
       return ret;

     while (1) {
            uint32_t cmd;
            struct binder_transaction_data_secctx tr;     
            struct binder_transaction_data *trd = &tr.transaction_data; 
            struct binder_work *w = NULL; 
            switch (w->type) {
                case BINDER_WORK_TRANSACTION: {
                   ...
                } break; 
                case BINDER_WORK_RETURN_ERROR: {
                  ...
                } break;}
done:
*consumed = ptr - buffer; 
binder_inner_proc_lock(proc);

//        ,     binder_thread,           BR_SPAWN_LOOPER        
if (proc->requested_threads == 0 && list_empty(&thread->proc->waiting_threads) && proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
/*spawn a new thread if we leave this out */) { 
    proc->requested_threads++;
    binder_inner_proc_unlock(proc);
//        BR_SPAWN_LOOPER
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer)) 
    return -EFAULT;
    binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
} else
    binder_inner_proc_unlock(proc);
return 0;
}
引き続きユーザープロセスIPCThreadStateを見て、どうやってBR_を処理しますか?SPAWN_LOOPAR
status_t IPCThreadState::executeCommand(int32_t cmd)
{
    switch ((uint32_t)cmd) {
        mProcess->spawnPooledThread(false);
        break;
    }
    return result;
}
ServiceManagerサービスの取得
その前に、いくつかのデータ構造を紹介します.
IBinder
class IBinder : public virtual RefBase
{
public:
    virtual sp<IInterface>  queryLocalInterface(const String16& descriptor);
    //         IInterface
    virtual status_t pingBinder() = 0;
    virtual status_t transact(uint32_t code,  const Parcel& data, Parcel* reply, uint32_t flags = 0) = 0;
   //   IPC  
    virtual status_t  linkToDeath(const sp<DeathRecipient>& recipient, void* cookie = NULL, 
    uint32_t flags = 0) = 0;
    //       
    virtual BBinder* localBinder();
    //       ,    BBinder,   binder  
    virtual BpBinder* remoteBinder();
    //      ,    BpBinder,  binder    
}
BBinder
ユーザプロセス空間において、binderエンティティを表す.
class BBinder : public IBinder 
{
protected:
    virtual status_t  onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
    //   IPC  
private:
    std::atomic<Extras*> mExtras; 
    void* mReserved0;
}
BPBinder
ユーザプロセス空間で、binderエージェントを表します.
//       ,   binder_ref handle  
class BpBinder : public IBinder
{
public:
    inline  int32_t  handle() const { return mHandle; }
    virtual status_t    transact(   uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
    //   IPC  
        KeyedVector<const void*, entry_t> mObjects;
    };
private:
    const   int32_t             mHandle;
    mutable Mutex               mLock;
    volatile int32_t    mAlive;
    volatile int32_t    mObitsSent;
    Vector<Obituary>*   mObituaries;
    ObjectManager       mObjects;
    Parcel*             mConstantData;
    mutable String16            mDescriptorCache;
};
すべてのプロセスがServiceMangerを取得するのはIServiceMnager.cppの静的な方法である.
アプリでServiceManagerを取得すると、ServiceManagerの代理を取得し、binder駆動の角度から見ると、App対応のbinder_です.procは対応するビッドカーを取得します.refは、Appユーザーのプロセスを見て、AppはServiceManagerに対応するBpBinderを取得します.
// framework/native/libs/binder/IServiceMnager.cpp
sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
            if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
    return gDefaultServiceManager;
}
ProcessState::self()->get Contact Object(NULL)からServiceManagerを取得し、空であればServiceManagerプロセスがまだ起きていないと説明し、sleepに入り、再度循環して取得し、空でないまで再度取得します.
ProcesStateはプロセスの一例で、現在のプロセス状態を表します.
// frameworks/native/libs/binder/ProcessState.cppkkj
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    //      0, ServiceManager BpBinder
    return getStrongProxyForHandle(0);
}

struct handle_entry {
      IBinder* binder; //   BBinder  BpBinder
      RefBase::weakref_type* refs;
};

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
    //      BBinder  BpBinder,     BpBinder
    handle_entry* e = lookupHandleLocked(handle);
    if (e != NULL) {
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) { // handle 0, ServiceManager
                Parcel data;
                //    binder_ioctl,     handle   binder    
                status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
            //   BpBinder
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    return result;
}
詳細な参照:http://gityuan.com/2016/10/29/binder-thread-pool/
Processistate::self()->get Contect Object(NULL)アプリを利用してServiceManagerのBpBinderを取得しましたが、BpBinderのhandleは0です.
gDefault ServiceManager=interface_cast(Processist::self()->get Contect Object(NULL);IServiceManagerに変換し、続いてAppプロセスはServiceManagerに照会する必要があるサービスですが、実はbinderのプロセスをまたぐ通信です.