Android 之 ServiceManager與服務管理
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函式中可以看出,它主要做了三件事情:
開啟/dev/binder裝置,並在記憶體中對映128K的空間。通知Binder裝置,把自己變成context_manager進入迴圈,不停的去讀Binder裝置,看是否有對service的請求,如果有的話,就去呼叫svcmgr_handler函式回撥處理請求。服務註冊
再來看看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的功能圖:
相關文章
- 日誌服務之告警接入與管理
- 高效管理 Android 前臺服務Android
- 患者管理之服務包
- 服務與服務之間的呼叫
- Android Manager之PowerManager(電源服務)Android
- 服務與資料之爭
- 字典服務的設計與管理
- Android效能優化篇之服務優化Android優化
- Redis服務之叢集節點管理Redis
- weblogic 受管理服務與nodemanger節點之間連線的配置Web
- 避坑指南之財務共享中心的服務管理
- 微服務SpringCloud之服務註冊與發現微服務SpringGCCloud
- 服務管理與通訊,基礎原理分析
- 服務註冊與發現之ETCD
- SpringCloud之服務提供與呼叫(Ribbon,Feign)SpringGCCloud
- springcloud之服務註冊與發現SpringGCCloud
- Android入門教程 | 四大元件之Service(前臺服務,後臺服務)Android元件
- Android四大元件之服務————服務的生命週期和啟動方式Android元件
- Windows 服務管理Windows
- Linux服務管理Linux
- 微服務Consul系列之服務註冊與發現微服務
- 在Android、iOS、Web多平臺使用AppGallery Connect效能管理服務AndroidiOSWebAPP
- IT 服務管理:一站式智慧運維管理服務運維
- Android系統服務DropBoxManagerService詳解與實踐應用Android
- 日誌服務之資料清洗與入湖
- spring cloud gateway之服務註冊與發現SpringCloudGateway
- android模擬器無服務Android
- 資料服務基礎能力之後設資料管理
- 雲端計算管理平臺之OpenStack映象服務glance
- IT服務管理是什麼?
- eureka如何管理服務呼叫
- ansible批量管理服務 上
- Android硬體服務框架例項之Vibrator(驅動到應用)Android框架
- 服務發現與配置管理高可用最佳實踐
- linux之nfs服務LinuxNFS
- linux之lsync服務Linux
- SpringCloud之服務呼叫SpringGCCloud
- apollo之ConfigService服務Gse
- 微服務的服務間通訊與服務治理微服務