Android 之 ServiceManager與服務管理

來源:互聯網
上載者:User

    ServiceMananger是android中比較重要的一個進程,它是在init進程啟動之後啟動,從名字上就可以看出來它是用來管理系統中的service。比如:InputMethodService、ActivityManagerService等。在ServiceManager中有兩個比較重要的方法:add_service、check_service。系統的service需要通過add_service把自己的資訊註冊到ServiceManager中,當需要使用時,通過check_service檢查該service是否存在。

    主函數

    從它的主函數代碼開始:

    int main(int argc, char **argv){    struct binder_state *bs;    void *svcmgr = BINDER_SERVICE_MANAGER;    bs = binder_open(128*1024);    if (binder_become_context_manager(bs)) {        LOGE("cannot become context manager (%s)\n", strerror(errno));        return -1;    }    svcmgr_handle = svcmgr;    binder_loop(bs, svcmgr_handler);    return 0;}

    從main函數中可以看出,它主要做了三件事情:

  1. 開啟/dev/binder裝置,並在記憶體中映射128K的空間。
  2. 通知Binder裝置,把自己變成context_manager
  3. 進入迴圈,不停的去讀Binder裝置,看是否有對service的請求,如果有的話,就去調用svcmgr_handler函數回調處理請求。
  4. 服務註冊

    再來看看ServiceManager中是怎麼樣去註冊服務的。先來看先,當有對service的請求時,調用的回呼函數svcmgr_handler:

    int svcmgr_handler(struct binder_state *bs,                   struct binder_txn *txn,                   struct binder_io *msg,                   struct binder_io *reply){    struct svcinfo *si;    uint16_t *s;    unsigned len;    void *ptr;    uint32_t strict_policy;//  LOGI("target=%p code=%d pid=%d uid=%d\n",//  txn->target, txn->code, txn->sender_pid, txn->sender_euid);    if (txn->target != svcmgr_handle)        return -1;    // Equivalent to Parcel::enforceInterface(), reading the RPC    // header with the strict mode policy mask and the interface name.    // Note that we ignore the strict_policy and don't propagate it    // further (since we do no outbound RPCs anyway).    strict_policy = bio_get_uint32(msg);    s = bio_get_string16(msg, &len);    if ((len != (sizeof(svcmgr_id) / 2)) ||        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {        fprintf(stderr,"invalid id %s\n", str8(s));        return -1;    }    switch(txn->code) {    case SVC_MGR_GET_SERVICE:    case SVC_MGR_CHECK_SERVICE:        s = bio_get_string16(msg, &len);        ptr = do_find_service(bs, s, len);        if (!ptr)            break;        bio_put_ref(reply, ptr);        return 0;    case SVC_MGR_ADD_SERVICE:        s = bio_get_string16(msg, &len);        ptr = bio_get_ref(msg);        if (do_add_service(bs, s, len, ptr, txn->sender_euid))            return -1;        break;    case SVC_MGR_LIST_SERVICES: {        unsigned n = bio_get_uint32(msg);        si = svclist;        while ((n-- > 0) && si)            si = si->next;        if (si) {            bio_put_string16(reply, si->name);            return 0;        }        return -1;    }    default:        LOGE("unknown code %d\n", txn->code);        return -1;    }    bio_put_uint32(reply, 0);    return 0;}

    在該回呼函數中會判斷Service有什麼需要,如果是請求註冊service,那麼久執行:

    case SVC_MGR_ADD_SERVICE:        s = bio_get_string16(msg, &len);        ptr = bio_get_ref(msg);        if (do_add_service(bs, s, len, ptr, txn->sender_euid))            return -1;        break;

    我們再來看看do_add_service中做了什麼事情:

    int do_add_service(struct binder_state *bs,                   uint16_t *s, unsigned len,                   void *ptr, unsigned uid){    struct svcinfo *si;//    LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);    if (!ptr || (len == 0) || (len > 127))        return -1;    if (!svc_can_register(uid, s)) {        LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",             str8(s), ptr, uid);        return -1;    }    si = find_svc(s, len);    if (si) {        if (si->ptr) {            LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",                 str8(s), ptr, uid);            return -1;        }        si->ptr = ptr;    } else {        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));        if (!si) {            LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",                 str8(s), ptr, uid);            return -1;        }        si->ptr = ptr;        si->len = len;        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));        si->name[len] = '\0';        si->death.func = svcinfo_death;        si->death.ptr = si;        si->next = svclist;        svclist = si;    }    binder_acquire(bs, ptr);    binder_link_to_death(bs, ptr, &si->death);    return 0;}

    在該函數中,首先會去檢查是否有許可權註冊service,如果沒有許可權就直接返回,不能註冊。

    if (!svc_can_register(uid, s)) {        LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",             str8(s), ptr, uid);        return -1;    }

    然後會去檢查該service是否已經註冊過了,如果已經註冊過,那麼就不能再註冊了:

      si = find_svc(s, len);  if (si) {        if (si->ptr) {            LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",                 str8(s), ptr, uid);            return -1;        }        si->ptr = ptr;    }

    再判斷記憶體是否足夠:

    si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));        if (!si) {            LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",                 str8(s), ptr, uid);            return -1;        }

    如果都沒什麼問題,會註冊該service,加入到svcList中來。注意,在ServiceManager中維護service資訊的地方就是svclist。裡面存了service的name和handler。

    服務擷取

    通過以上幾個步驟,service就算註冊成功了。那麼當要獲得該service的時候又是怎麼去處理的。還是來看下回呼函數中的判斷:

    case SVC_MGR_CHECK_SERVICE:        s = bio_get_string16(msg, &len);        ptr = do_find_service(bs, s, len);        if (!ptr)            break;        bio_put_ref(reply, ptr);        return 0;

    如果是擷取service,那麼執行SVC_MGR_CHECK_SERVICE,並把返回的資料寫入reply,返回給用戶端。

    do_find_service函數中主要執行service的尋找。

    void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len){    struct svcinfo *si;    si = find_svc(s, len);//    LOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);    if (si && si->ptr) {        return si->ptr;    } else {        return 0;    }}

    這樣在ServiceManager中就完成了服務的註冊和尋找。來看下ServiceManager的功能圖:

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.