Android跨進(jìn)程通信IPC之13——Binder之native層C++篇--ServiceManager的核心服務(wù)

移步系列Android跨進(jìn)程通信IPC系列

通過上面的代碼我們知道service manager的核心服務(wù)主要有4個(gè)

  • do_add_service()函數(shù):注冊(cè)服務(wù)
  • do_find_service()函數(shù):查找服務(wù)
  • binder_link_to_death()函數(shù):結(jié)束服務(wù)
  • binder_send_reply()函數(shù):將注冊(cè)結(jié)果返回給Binder驅(qū)動(dòng)

1 do_add_service()函數(shù) 注冊(cè)服務(wù)

//service_manager.c      194行
int do_add_service(struct binder_state *bs,
                   const uint16_t *s, size_t len,
                   uint32_t handle, uid_t uid, int allow_isolated,
                   pid_t spid)
{
    struct svcinfo *si;

    if (!handle || (len == 0) || (len > 127))
        return -1;

    //權(quán)限檢查
    if (!svc_can_register(s, len, spid)) {
        return -1;
    }

    //服務(wù)檢索
    si = find_svc(s, len);
    if (si) {
        if (si->handle) {
            svcinfo_death(bs, si); //服務(wù)已注冊(cè)時(shí),釋放相應(yīng)的服務(wù)
        }
        si->handle = handle;
    } else {
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) { 
           //內(nèi)存不足,無法分配足夠內(nèi)存
            return -1;
        }
        si->handle = handle;
        si->len = len;
        //內(nèi)存拷貝服務(wù)信息
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = '\0';
        si->death.func = (void*) svcinfo_death;
        si->death.ptr = si;
        si->allow_isolated = allow_isolated;
        // svclist保存所有已注冊(cè)的服務(wù)
        si->next = svclist; 
        svclist = si;
    }

    //以BC_ACQUIRE命令,handle為目標(biāo)的信息,通過ioctl發(fā)送給binder驅(qū)動(dòng)
    binder_acquire(bs, handle);
    //以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通過ioctl發(fā)送給binder驅(qū)動(dòng),主要用于清理內(nèi)存等收尾工作。
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}

注冊(cè)服務(wù)部分主要分塊內(nèi)容:

  • svc_can_register:檢查權(quán)限:檢查selinux權(quán)限是否滿足
  • find_svc:服務(wù)檢索,根據(jù)服務(wù)名來查詢匹配的服務(wù);
  • svcinfo_death:釋放服務(wù),當(dāng)查詢到已存在的同名的服務(wù),則先清理該服務(wù)信息,再講當(dāng)前的服務(wù)加入到服務(wù)列表svclist;

1.1 svc_can_register()函數(shù)

//service_manager.c      110行
static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
{
    const char *perm = "add";
    //檢查selinux權(quán)限是否滿足
    return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
}

1.2 svcinfo_death()函數(shù)

//service_manager.c      153行
void svcinfo_death(struct binder_state *bs, void *ptr)
{
    struct svcinfo *si = (struct svcinfo* ) ptr;

    if (si->handle) {
        binder_release(bs, si->handle);
        si->handle = 0;
    }
}

3 bio_get_ref()函數(shù)

// framework/native/cmds/servicemanager/binder.c     627行
uint32_t bio_get_ref(struct binder_io *bio)
{
    struct flat_binder_object *obj;

    obj = _bio_get_obj(bio);
    if (!obj)
        return 0;

    if (obj->type == BINDER_TYPE_HANDLE)
        return obj->handle;

    return 0;
}

2 do_find_service() 查找服務(wù)

//service_manager.c      170行
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
    //具體查詢相應(yīng)的服務(wù)
    struct svcinfo *si = find_svc(s, len);
    if (!si || !si->handle) {
        return 0;
    }

    if (!si->allow_isolated) {
        uid_t appid = uid % AID_USER;
         //檢查該服務(wù)是否允許孤立于進(jìn)程而單獨(dú)存在
        if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
            return 0;
        }
    }
     //服務(wù)是否滿足于查詢條件
    if (!svc_can_find(s, len, spid)) {
        return 0;
    }
   /返回結(jié)點(diǎn)中的ptr,這個(gè)ptr是binder中對(duì)應(yīng)的binder_ref.des
    return si->handle;
}

主要就是查詢目標(biāo)服務(wù),并返回該服務(wù)所對(duì)應(yīng)的handle

2.1 find_svc()函數(shù)

//service_manager.c      140行
struct svcinfo *find_svc(const uint16_t *s16, size_t len)
{
    struct svcinfo *si;
    for (si = svclist; si; si = si->next) {
        //當(dāng)名字完全一致,則返回查詢到的結(jié)果
        if ((len == si->len) &&
            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
            return si;
        }
    }
    return NULL;
}

在svclist服務(wù)列表中,根據(jù)服務(wù)名遍歷查找是否已經(jīng)注冊(cè)。當(dāng)服務(wù)已經(jīng)存在svclist,則返回相應(yīng)的服務(wù)名,否則返回null。


在svcmgr_handler中當(dāng)執(zhí)行完do_find_service()函數(shù)后,會(huì)調(diào)用bio_put_ref()函數(shù),將handle封裝到reply.
bio_put_ref()函數(shù)

// framework/native/cmds/servicemanager/binder.c    505行
void bio_put_ref(struct binder_io *bio, uint32_t handle)
{
    //構(gòu)造了一個(gè)flat_binder_object
    struct flat_binder_object *obj;
    if (handle)
        obj = bio_alloc_obj(bio); 
    else
        obj = bio_alloc(bio, sizeof(*obj));
    if (!obj)
        return;
    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    obj->type = BINDER_TYPE_HANDLE; //返回的是HANDLE類型
    //以service manager的身份回應(yīng)給kernel driver,ptr就是handler對(duì)應(yīng)的ref索引值 1,2,3,4,5,6等
    obj->handle = handle;
    obj->cookie = 0;
}

這個(gè)段代碼也不復(fù)雜,就是根據(jù)handle來判斷分別執(zhí)行bio_alloc_obj()函數(shù)和bio_alloc()函數(shù)
bio_alloc_obj()函數(shù)

// framework/native/cmds/servicemanager/binder.c   468 行 
static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
{
    struct flat_binder_object *obj;
    obj = bio_alloc(bio, sizeof(*obj));

    if (obj && bio->offs_avail) {
        bio->offs_avail--;
        *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
        return obj;
    }
    bio->flags |= BIO_F_OVERFLOW;
    return NULL;
}

bio_alloc()函數(shù)

// framework/native/cmds/servicemanager/binder.c   437 行 
static void *bio_alloc(struct binder_io *bio, size_t size)
{
    size = (size + 3) & (~3);
    if (size > bio->data_avail) {
        bio->flags |= BIO_F_OVERFLOW;
        return NULL;
    } else {
        void *ptr = bio->data;
        bio->data += size;
        bio->data_avail -= size;
        return ptr;
    }
}

3 binder_link_to_death() 函數(shù)

// framework/native/cmds/servicemanager/binder.c        305行
void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
{
    struct {
        uint32_t cmd;
        struct binder_handle_cookie payload;
    } __attribute__((packed)) data;

    data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
    data.payload.handle = target;
    data.payload.cookie = (uintptr_t) death;
    binder_write(bs, &data, sizeof(data));
}

binder_write和前面的binder_write一樣,進(jìn)入Binder driver后,直接調(diào)用binder_thread_write,處理BC_REQUEST_DEATH_NOTIFICATION命令。其中binder_ioctl_write_read()函數(shù),前面面已經(jīng)講解過了。這里就不詳細(xì)講解了

3.1 binder_thread_write() 函數(shù)

//kernel/drivers/android/binder.c    2248行
static int binder_thread_write(struct binder_proc *proc,
            struct binder_thread *thread,
            binder_uintptr_t binder_buffer, size_t size,
            binder_size_t *consumed)
{
    uint32_t cmd;
    struct binder_context *context = proc->context;
    void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
    void __user *ptr = buffer + *consumed;
    void __user *end = buffer + size;
    while (ptr < end && thread->return_error == BR_OK) {
        //獲取命令
        get_user(cmd, (uint32_t __user *)ptr); 
        switch (cmd) {
              //**** 省略部分代碼 ****
              // 注冊(cè)死亡通知
             case BC_REQUEST_DEATH_NOTIFICATION:
         case BC_CLEAR_DEATH_NOTIFICATION: { 
              uint32_t target;
            void __user *cookie;
            struct binder_ref *ref;
            struct binder_ref_death *death;
            //獲取taget
            get_user(target, (uint32_t __user *)ptr); 
            ptr += sizeof(uint32_t);
            /獲取death
            get_user(cookie, (void __user * __user *)ptr); /
            ptr += sizeof(void *);
            //拿到目標(biāo)服務(wù)的binder_ref
            ref = binder_get_ref(proc, target); 
            if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
                 //已設(shè)死亡通知
                if (ref->death) {
                    break; 
                }
                death = kzalloc(sizeof(*death), GFP_KERNEL);
                INIT_LIST_HEAD(&death->work.entry);
                death->cookie = cookie;
                ref->death = death;
                //當(dāng)目標(biāo)服務(wù)所在進(jìn)程已死,則發(fā)送死亡通知
                if (ref->node->proc == NULL) {
                    //當(dāng)前線程為binder線程,則直接添加到當(dāng)前線程的TODO隊(duì)列
                    ref->death->work.type = BINDER_WORK_DEAD_BINDER;
                    if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
                        list_add_tail(&ref->death->work.entry, &thread->todo);
                    } else {
                        list_add_tail(&ref->death->work.entry, &proc->todo);
                        wake_up_interruptible(&proc->wait);
                    }
                }
            } else {
                ...
            }
        } break;
       //**** 省略部分代碼 ****
    }
       //**** 省略部分代碼 ****
    return 0;
}
  • 此方法中的proc,thread都是指當(dāng)前的servicemanager進(jìn)程信息,此時(shí)TODO隊(duì)列有數(shù)據(jù),則進(jìn)入binder_thread_read。
  • 那么問題來了,哪些場(chǎng)景會(huì)向隊(duì)列增加BINDER_WORK_READ_BINDER事物?那邊是當(dāng)binder所在進(jìn)程死亡后,會(huì)調(diào)用binder_realse方法,然后調(diào)用binder_node_release這個(gè)過程便會(huì)發(fā)出死亡通知的回調(diào)。

3.2 binder_thread_read() 函數(shù)

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)
    ...
    //只有當(dāng)前線程todo隊(duì)列為空,并且transaction_stack也為空,才會(huì)開始處于當(dāng)前進(jìn)程的事務(wù)
    if (wait_for_proc_work) {
        ...
        ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
    } else {
        ...
        ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
    }
    //加鎖
    binder_lock(__func__);
    if (wait_for_proc_work)
        //空閑的binder線程減1
        proc->ready_threads--; 
    thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
    while (1) {
        uint32_t cmd;
        struct binder_transaction_data tr;
        struct binder_work *w;
        struct binder_transaction *t = NULL;
        //從todo隊(duì)列拿出前面放入的binder_work, 此時(shí)type為BINDER_WORK_DEAD_BINDER
        if (!list_empty(&thread->todo)) {
            w = list_first_entry(&thread->todo, struct binder_work,
                         entry);
        } else if (!list_empty(&proc->todo) && wait_for_proc_work) {
            w = list_first_entry(&proc->todo, struct binder_work,
                         entry);
        }

        switch (w->type) {
            case BINDER_WORK_DEAD_BINDER: {
              struct binder_ref_death *death;
              uint32_t cmd;

              death = container_of(w, struct binder_ref_death, work);
              if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
                  ...
              else
              //進(jìn)入此分支
                  cmd = BR_DEAD_BINDER; 
              //拷貝用戶空間
              put_user(cmd, (uint32_t __user *)ptr);
              ptr += sizeof(uint32_t);

              //此處的cookie是前面?zhèn)鬟f的svcinfo_death
              put_user(death->cookie, (binder_uintptr_t __user *)ptr);
              ptr += sizeof(binder_uintptr_t);

              if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
                  ...
              } else
                  list_move(&w->entry, &proc->delivered_death);
              if (cmd == BR_DEAD_BINDER)
                  goto done;
            } break;
        }
    }
    ...
    return 0;
}
  • 將命令BR_DEAD_BINDER寫到用戶空間,此處的cookie是前面?zhèn)鬟f的svcinfo_death。當(dāng)binder_loop下一次執(zhí)行binder_parse的過程便會(huì)處理該消息。
  • binder_parse()函數(shù)和svcinfo_death()函數(shù)上面已經(jīng)說明了,這里就不詳細(xì)說明了。

3.3 binder_release() 函數(shù)

//frameworks/native/cmds/servicemanager/binder.c   297行
void binder_release(struct binder_state *bs, uint32_t target)
{
    uint32_t cmd[2];
    cmd[0] = BC_RELEASE;
    cmd[1] = target;
    binder_write(bs, cmd, sizeof(cmd));
}

向Binder Driver寫入BC_RELEASE命令,最終進(jìn)入Binder Driver后執(zhí)行binder_dec_ref(ref,1) 來減少binder node的引用。

4 binder_send_reply() 函數(shù) 將注冊(cè)結(jié)果返回給Binder驅(qū)動(dòng)

//frameworks/native/cmds/servicemanager/binder.c   170行
    void binder_send_reply(struct binder_state *bs,
                           struct binder_io *reply,
                           binder_uintptr_t buffer_to_free,
                           int status) {
        struct {
            uint32_t cmd_free;
            binder_uintptr_t buffer;
            uint32_t cmd_reply;
            struct binder_transaction_data txn;
        } __attribute__((packed)) data;
        //free buffer命令
        data.cmd_free = BC_FREE_BUFFER;
        data.buffer = buffer_to_free;
        //replay命令
        data.cmd_reply = BC_REPLY;
        data.txn.target.ptr = 0;
        data.txn.cookie = 0;
        data.txn.code = 0;
        if (status) {
            data.txn.flags = TF_STATUS_CODE;
            data.txn.data_size = sizeof(int);
            data.txn.offsets_size = 0;
            data.txn.data.ptr.buffer = (uintptr_t) & status;
            data.txn.data.ptr.offsets = 0;
        } else {
            data.txn.flags = 0;
            data.txn.data_size = reply -> data - reply -> data0;
            data.txn.offsets_size = ((char*)reply -> offs)-((char*)reply -> offs0);
            data.txn.data.ptr.buffer = (uintptr_t) reply -> data0;
            data.txn.data.ptr.offsets = (uintptr_t) reply -> offs0;
        }
        //向Binder驅(qū)動(dòng)通信
        binder_write(bs, & data, sizeof(data));
    }

執(zhí)行binder_parse方法,先調(diào)用svcmgr_handler()函數(shù),然后再執(zhí)行binder_send_reply過程,該過程會(huì)調(diào)用binder_write進(jìn)入binder驅(qū)動(dòng)后,將BC_FREE_BUFFER和BC_REPLY命令協(xié)議發(fā)送給Binder驅(qū)動(dòng),向Client端發(fā)送reply,其中data數(shù)據(jù)區(qū)中保存的是TYPE為HANDLE。

參考

Android跨進(jìn)程通信IPC之9——Binder之Framework層C++篇1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容