小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

system

 一楠tech 2019-09-11

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

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

驗(yàn)證了下,返回的am確實(shí)是AMS的實(shí)例,沒問題

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

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


Binder IPC模型

 

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

 

兩個(gè)典型流程

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

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

 

回到開始問題:

上面的步驟是在Client端請求AMS服務(wù),這里Client與AMS在兩個(gè)不同進(jìn)程,
而如果在同一進(jìn)程,AMS運(yùn)行在system_server進(jìn)程中,如果其他服務(wù)線程通過SystemManager.getService("activity")請求AMS服務(wù),
那么這個(gè)接口將直接返回 ActivityManagerService實(shí)例的引用。
原因主要是在case 2步驟中藍(lán)色部分,binder驅(qū)動(dòng)會進(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)程是否是同一個(gè),
如果是,則改寫fp->type為BINDER_TYPE_BINDER,設(shè)fp->binder = ref->node->ptr;
后續(xù)把AMS的binder實(shí)體中的實(shí)例引用返回給請求者,

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

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多