乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      system

       一楠tech 2019-09-11

      我們知道ActivityManager是運行在system_service進(jìn)程里的,但是最近看代碼發(fā)現(xiàn)在這個進(jìn)程的其他服務(wù)線程里為了獲取AMS調(diào)用:

      ActivityManagerService am = (ActivityManagerService)ServiceManager.getService("activity");

      驗證了下,返回的am確實是AMS的實例,沒問題

      我們一般用ServiceManager.getService在其他進(jìn)程中獲取AMS服務(wù),返回的一個是遠(yuǎn)端binder代理,

      如果用在同一進(jìn)程中會怎樣? 為了解釋這個問題,首先要復(fù)習(xí)下binder通信知識


      Binder IPC模型

       

      Binder在內(nèi)核中兩種形式: Binder實體(binder_node), Binder引用(binder_ref)
      binder_node:
      {
        binder_proc* proc; //service進(jìn)程信息
        void__user* ptr; //service實例指針
      }
      binder_ref:
      {
        binder_proc* proc; //service進(jìn)程信息
        binder_node* node; //指向Binder實體
        unit32_t desc; //service handle值,唯一標(biāo)識一個service
      }

       

      兩個典型流程

      1. service在ServiceManager注冊:
        在內(nèi)核創(chuàng)建一個binder實體(橙色矩形),一個binder引用(藍(lán)色六邊形),
        在ServiceManager里用map保存這個service的名字和binder引用(藍(lán)色曲線四邊形)。
      2. Client通過ServiceManager getService("activity"):
        Client首先與ServiceManager進(jìn)程通信
        Client端先構(gòu)造一個handle為0的binder引用(灰色曲線四邊形),
        通過這個引用向內(nèi)核發(fā)送數(shù)據(jù)(包含servcie的名字"activity"),
        在內(nèi)核空間創(chuàng)建一個ServiceManager的biner引用(灰色六邊形),
        找到ServiceManager的binder實體(灰色矩形),
        然后喚醒ServiceManager進(jìn)程,
        通過binder實體中的ServiceManager實例,調(diào)用它的getService方法,
        ServiceManager通過名字"activity"找到ActivityManagerService服務(wù)的binder引用,把數(shù)據(jù)寫回內(nèi)核
        在內(nèi)核為Client進(jìn)程創(chuàng)建一個ActivityManagerService binder引用(藍(lán)色六邊形)
        返回包含binder的handle值的數(shù)據(jù)給Client,在Client創(chuàng)建一個app端的binder引用(藍(lán)色曲線四邊形)

        然后Client可以通過這個app端的binder引用與AMS進(jìn)行通信。
        在app-service通信中,binder內(nèi)核驅(qū)動擔(dān)任dns的功能,也就是通過binder引用,找對應(yīng)服務(wù)的binder實體

       

      回到開始問題:

      上面的步驟是在Client端請求AMS服務(wù),這里Client與AMS在兩個不同進(jìn)程,
      而如果在同一進(jìn)程,AMS運行在system_server進(jìn)程中,如果其他服務(wù)線程通過SystemManager.getService("activity")請求AMS服務(wù),
      那么這個接口將直接返回 ActivityManagerService實例的引用。
      原因主要是在case 2步驟中藍(lán)色部分,binder驅(qū)動會進(jìn)行檢查:

       

      復(fù)制代碼
      static void binder_transaction(struct binder_proc *proc,
                         struct binder_thread *thread,
                         struct binder_transaction_data *tr, int reply)
      {
      switch (fp->type) {
      ...
              case BINDER_TYPE_HANDLE:
              case BINDER_TYPE_WEAK_HANDLE: {
                  struct binder_ref *ref = binder_get_ref(proc, fp->handle,
                              fp->type == BINDER_TYPE_HANDLE);
      
                  if (ref == NULL) {
                      binder_user_error("%d:%d got transaction with invalid handle, %d\n",
                              proc->pid,
                              thread->pid, fp->handle);
                      return_error = BR_FAILED_REPLY;
                      goto err_binder_get_ref_failed;
                  }
                  if (ref->node->proc == target_proc) {
                      if (fp->type == BINDER_TYPE_HANDLE)
                          fp->type = BINDER_TYPE_BINDER;
                      else
                          fp->type = BINDER_TYPE_WEAK_BINDER;
                      fp->binder = ref->node->ptr;
                      fp->cookie = ref->node->cookie;
                      binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
                      trace_binder_transaction_ref_to_node(t, ref);
                      binder_debug(BINDER_DEBUG_TRANSACTION,
                               "        ref %d desc %d -> node %d u%016llx\n",
                               ref->debug_id, ref->desc, ref->node->debug_id,
                               (u64)ref->node->ptr);
                  } else {
                      struct binder_ref *new_ref;
      
                      new_ref = binder_get_ref_for_node(target_proc, ref->node);
                      if (new_ref == NULL) {
                          return_error = BR_FAILED_REPLY;
                          goto err_binder_get_ref_for_node_failed;
                      }
                      fp->binder = 0;
                      fp->handle = new_ref->desc;
                      fp->cookie = 0;
                      binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
                      trace_binder_transaction_ref_to_ref(t, ref,
                                          new_ref);
                      binder_debug(BINDER_DEBUG_TRANSACTION,
                               "        ref %d desc %d -> ref %d desc %d (node %d)\n",
                               ref->debug_id, ref->desc, new_ref->debug_id,
                               new_ref->desc, ref->node->debug_id);
                  }
              } break;
      ...
      }
      }
      復(fù)制代碼

       

      看紅色代碼
      首先判斷ref->node->proc == target_proc,即判斷注冊的AMS進(jìn)程和要獲取AMS的進(jìn)程是否是同一個,
      如果是,則改寫fp->type為BINDER_TYPE_BINDER,設(shè)fp->binder = ref->node->ptr;
      后續(xù)把AMS的binder實體中的實例引用返回給請求者,

      所以通過SystemManager.getService("name")在同一進(jìn)程獲取服務(wù),會直接返回這個服務(wù)實例的引用,這是binder驅(qū)動支持的。 當(dāng)然在一個進(jìn)程里有更直接的辦法來獲取,但是在某些特殊情況用這種辦法也可以,只是效率稍低,因為經(jīng)歷了一次與serviceManager的ipc。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多