Android之ServiceManager與服務(wù)管理

    轉(zhuǎn)載處:http://blog.csdn.net/xieqibao/article/details/6585143

    創(chuàng)新互聯(lián)是一家專業(yè)提供津南企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、成都做網(wǎng)站、H5技術(shù)、小程序制作等業(yè)務(wù)。10年已為津南眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站設(shè)計(jì)公司優(yōu)惠進(jìn)行中。

    ServiceMananger是android中比較重要的一個進(jìn)程,它是在init進(jìn)程啟動之后啟動,從名字上就可以看出來它是用來管理系統(tǒng)中的service。比如:InputMethodService、ActivityManagerService等。在ServiceManager中有兩個比較重要的方法:add_service、check_service。系統(tǒng)的service需要通過add_service把自己的信息注冊到ServiceManager中,當(dāng)需要使用時(shí),通過check_service檢查該service是否存在。

    主函數(shù)

    從它的主函數(shù)代碼開始:

    [java] view plaincopy
    1. int main(int argc, char **argv)  
    2. {  
    3.     struct binder_state *bs;  
    4.     void *svcmgr = BINDER_SERVICE_MANAGER;  
    5.     bs = binder_open(128*1024);  
    6.     if (binder_become_context_manager(bs)) {  
    7.         LOGE("cannot become context manager (%s)\n", strerror(errno));  
    8.         return -1;  
    9.     }  
    10.     svcmgr_handle = svcmgr;  
    11.     binder_loop(bs, svcmgr_handler);  
    12.     return 0;  
    13. }  

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

  1. 打開/dev/binder設(shè)備,并在內(nèi)存中映射128K的空間。
  2. 通知Binder設(shè)備,把自己變成context_manager
  3. 進(jìn)入循環(huán),不停的去讀Binder設(shè)備,看是否有對service的請求,如果有的話,就去調(diào)用svcmgr_handler函數(shù)回調(diào)處理請求。

    服務(wù)注冊

    再來看看ServiceManager中是怎么樣去注冊服務(wù)的。先來看先,當(dāng)有對service的請求時(shí),調(diào)用的回調(diào)函數(shù)svcmgr_handler:

    [java] view plaincopy
    1. int svcmgr_handler(struct binder_state *bs,  
    2.                    struct binder_txn *txn,  
    3.                    struct binder_io *msg,  
    4.                    struct binder_io *reply)  
    5. {  
    6.     struct svcinfo *si;  
    7.     uint16_t *s;  
    8.     unsigned len;  
    9.     void *ptr;  
    10.     uint32_t strict_policy;  
    11. //  LOGI("target=%p code=%d pid=%d uid=%d\n",  
    12. //  txn->target, txn->code, txn->sender_pid, txn->sender_euid);  
    13.     if (txn->target != svcmgr_handle)  
    14.         return -1;  
    15.     // Equivalent to Parcel::enforceInterface(), reading the RPC  
    16.     // header with the strict mode policy mask and the interface name.  
    17.     // Note that we ignore the strict_policy and don't propagate it  
    18.     // further (since we do no outbound RPCs anyway).  
    19.     strict_policy = bio_get_uint32(msg);  
    20.     s = bio_get_string16(msg, &len);  
    21.     if ((len != (sizeof(svcmgr_id) / 2)) ||  
    22.         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {  
    23.         fprintf(stderr,"invalid id %s\n", str8(s));  
    24.         return -1;  
    25.     }  
    26.     switch(txn->code) {  
    27.     case SVC_MGR_GET_SERVICE:  
    28.     case SVC_MGR_CHECK_SERVICE:  
    29.         s = bio_get_string16(msg, &len);  
    30.         ptr = do_find_service(bs, s, len);  
    31.         if (!ptr)  
    32.             break;  
    33.         bio_put_ref(reply, ptr);  
    34.         return 0;  
    35.     case SVC_MGR_ADD_SERVICE:  
    36.         s = bio_get_string16(msg, &len);  
    37.         ptr = bio_get_ref(msg);  
    38.         if (do_add_service(bs, s, len, ptr, txn->sender_euid))  
    39.             return -1;  
    40.         break;  
    41.     case SVC_MGR_LIST_SERVICES: {  
    42.         unsigned n = bio_get_uint32(msg);  
    43.         si = svclist;  
    44.         while ((n-- > 0) && si)  
    45.             si = si->next;  
    46.         if (si) {  
    47.             bio_put_string16(reply, si->name);  
    48.             return 0;  
    49.         }  
    50.         return -1;  
    51.     }  
    52.     default:  
    53.         LOGE("unknown code %d\n", txn->code);  
    54.         return -1;  
    55.     }  
    56.     bio_put_uint32(reply, 0);  
    57.     return 0;  
    58. }  

    在該回調(diào)函數(shù)中會判斷Service有什么需要,如果是請求注冊service,那么久執(zhí)行:

    [java] view plaincopy
    1. case SVC_MGR_ADD_SERVICE:  
    2.         s = bio_get_string16(msg, &len);  
    3.         ptr = bio_get_ref(msg);  
    4.         if (do_add_service(bs, s, len, ptr, txn->sender_euid))  
    5.             return -1;  
    6.         break;  

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

    [java] view plaincopy
    1. int do_add_service(struct binder_state *bs,  
    2.                    uint16_t *s, unsigned len,  
    3.                    void *ptr, unsigned uid)  
    4. {  
    5.     struct svcinfo *si;  
    6. //    LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);  
    7.     if (!ptr || (len == 0) || (len > 127))  
    8.         return -1;  
    9.     if (!svc_can_register(uid, s)) {  
    10.         LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",  
    11.              str8(s), ptr, uid);  
    12.         return -1;  
    13.     }  
    14.     si = find_svc(s, len);  
    15.     if (si) {  
    16.         if (si->ptr) {  
    17.             LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",  
    18.                  str8(s), ptr, uid);  
    19.             return -1;  
    20.         }  
    21.         si->ptr = ptr;  
    22.     } else {  
    23.         si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));  
    24.         if (!si) {  
    25.             LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",  
    26.                  str8(s), ptr, uid);  
    27.             return -1;  
    28.         }  
    29.         si->ptr = ptr;  
    30.         si->len = len;  
    31.         memcpy(si->name, s, (len + 1) * sizeof(uint16_t));  
    32.         si->name[len] = '\0';  
    33.         si->death.func = svcinfo_death;  
    34.         si->death.ptr = si;  
    35.         si->next = svclist;  
    36.         svclist = si;  
    37.     }  
    38.     binder_acquire(bs, ptr);  
    39.     binder_link_to_death(bs, ptr, &si->death);  
    40.     return 0;  
    41. }  

    在該函數(shù)中,首先會去檢查是否有權(quán)限注冊service,如果沒有權(quán)限就直接返回,不能注冊。

    [java] view plaincopy
    1. if (!svc_can_register(uid, s)) {  
    2.         LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",  
    3.              str8(s), ptr, uid);  
    4.         return -1;  
    5.     }  

    然后會去檢查該service是否已經(jīng)注冊過了,如果已經(jīng)注冊過,那么就不能再注冊了:

    [java] view plaincopy
    1. si = find_svc(s, len);  
    2. if (si) {  
    3.       if (si->ptr) {  
    4.           LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",  
    5.                str8(s), ptr, uid);  
    6.           return -1;  
    7.       }  
    8.       si->ptr = ptr;  
    9.   }  

    再判斷內(nèi)存是否足夠:

    [java] view plaincopy
    1. si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));  
    2.         if (!si) {  
    3.             LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",  
    4.                  str8(s), ptr, uid);  
    5.             return -1;  
    6.         }  

    如果都沒什么問題,會注冊該service,加入到svcList中來。注意,在ServiceManager中維護(hù)service信息的地方就是svclist。里面存了service的name和handler。

    服務(wù)獲取

    通過以上幾個步驟,service就算注冊成功了。那么當(dāng)要獲得該service的時(shí)候又是怎么去處理的。還是來看下回調(diào)函數(shù)中的判斷:

    [java] view plaincopy
    1. case SVC_MGR_CHECK_SERVICE:  
    2.         s = bio_get_string16(msg, &len);  
    3.         ptr = do_find_service(bs, s, len);  
    4.         if (!ptr)  
    5.             break;  
    6.         bio_put_ref(reply, ptr);  
    7.         return 0;  

    如果是獲取service,那么執(zhí)行SVC_MGR_CHECK_SERVICE,并把返回的數(shù)據(jù)寫入reply,返回給客戶端。

    do_find_service函數(shù)中主要執(zhí)行service的查找。

    [java] view plaincopy
    1. void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len)  
    2. {  
    3.     struct svcinfo *si;  
    4.     si = find_svc(s, len);  
    5. //    LOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);  
    6.     if (si && si->ptr) {  
    7.         return si->ptr;  
    8.     } else {  
    9.         return 0;  
    10.     }  
    11. }  

    這樣在ServiceManager中就完成了服務(wù)的注冊和查找。來看下ServiceManager的功能圖:

    Android 之 ServiceManager與服務(wù)管理


6

標(biāo)題名稱:Android之ServiceManager與服務(wù)管理
鏈接地址:http://bm7419.com/article4/jdsdoe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司網(wǎng)站設(shè)計(jì)公司、企業(yè)建站網(wǎng)站營銷、網(wǎng)站設(shè)計(jì)、電子商務(wù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)