日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Binder源码分析之ServiceManager(原)

發布時間:2025/3/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Binder源码分析之ServiceManager(原) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
ServiceManager作為Native層Service的管理員,有著極其重要的作用,主要表現兩個方面:
? ? ? ? 1、對于服務端來說,系統所有的服務提供者都需要向ServiceManager注冊。
? ? ? ? 2、對于客戶端來說,所有客戶端如果想要獲得某個系統服務的代理,必須向ServiceManager申請相應的服務端代理。

? ? ? ? 下面從源碼分析ServiceManager的啟動流程和服務流程。

[java]?view plaincopy
  • @Service_manager.c(frameworks/base/cmds/servicemanager)??
  • int?main(int?argc,?char?**argv)?{??
  • ????struct?binder_state?*bs;??
  • ????void?*svcmgr?=?BINDER_SERVICE_MANAGER;??
  • ????//打開binder設備??
  • ????bs?=?<span?style="color:#ff0000;">binder_open</span>(128*1024);??
  • ????//成為Service?manager??
  • ????if?(<span?style="color:#ff0000;">binder_become_context_manager</span>(bs))?{??
  • ????????LOGE("cannot?become?context?manager?(%s)\n",?strerror(errno));??
  • ????????return?-1;??
  • ????}??
  • ????svcmgr_handle?=?svcmgr;??
  • ????//在binder_loop中循環檢測binder中是否有新的請求??
  • ????<span?style="color:#ff0000;">binder_loop</span>(bs,?svcmgr_handler);??
  • ????return?0;??
  • }??
  • ? ? ? ? main函數主要有三個功能:
    ? ? ? ? 1、打開Binder設備文件;
    ? ? ? ? 2、告訴Binder驅動程序自己是Binder上下文管理者;
    ? ? ? ? 3、進入一個死循環,充當Service的角色,等待Client的請求。

    ? ? ? ? 下面我們就分別介紹這三個步驟。


    一、打開Binder設備

    [java]?view plaincopy
  • @binder.c(\frameworks\base\cmds\servicemanager\)??
  • struct?binder_state?*binder_open(unsigned?mapsize)?{??
  • ????//創建binder_state結構體并分配內存??
  • ????struct?binder_state?*bs;??
  • ????bs?=?malloc(sizeof(*bs));??
  • ????//打開binder設備??
  • ????bs->fd?=?open("/dev/binder",?O_RDWR);??
  • ????bs->mapsize?=?mapsize;??
  • ????//將binder物理空間映射為ServiceManager可用的虛擬空間??
  • ????bs->mapped?=?mmap(NULL,?mapsize,?PROT_READ,?MAP_PRIVATE,?bs->fd,?0);??
  • ????//將結構體返回給servicemanager??
  • ????return?bs;??
  • }??
  • ? ? ? ? 上面打開Binder設備的過程其實就是構建一個binder_state結構體對象,然后對其各個成員初始化的過程。我們來看一下binder_state數據結構: [java]?view plaincopy
  • struct?binder_state?{??
  • ????//文件描述符,這里指的是/dev/binder設備文件描述符??
  • ????int?fd;??
  • ????//把設備文件/dev/binder映射到進程空間的起始地址,這里就是128*1024??
  • ????void?*mapped;??
  • ????//映射的空間大小??
  • ????unsigned?mapsize;??
  • };??
  • ? ? ? ? 這個結構體只有三個成員變量,其中fd是底層binder設備的文件描述符,mapped是ServiceManager得到的虛擬空間地址,這塊虛擬空間映射了底層binder的物理地址,而mapsize是這塊虛擬空間的大小,也就是128*1024。
    ? ? ? ? 從上面可以看出,打開Binder的過程的過程分為兩步:
    ? ? ? ? 1、打開Binder設備;

    ? ? ? ? 2、用Binder的物理地址映射為ServiceManager可用的虛擬地址;


    二、ServiceManager成為服務管理員的過程

    ? ? ? ? 在Android中,每個注冊的Service,Binder都會給他分配一個唯一的int型的句柄,Client可以用該句柄向ServiceManager請求相應的Service,而負責這個管理任務的正是ServiceManager。也就是說,Service需要先向ServiceManager注冊自己,并得到自己的服務句柄,然后Client需要拿這個int型的句柄向ServiceManager請求相應的Service,ServiceManager再把相應的Service代理對象發送給Client使用
    ? ? ? ? 同時我們注意到,ServiceManager本身也是一個Service,他需要先向Binder注冊自己,而且要把自己注冊為“管理員”,那么這個注冊過程是怎樣的呢?我們來看源碼: [java]?view plaincopy
  • int?binder_become_context_manager(struct?binder_state?*bs)??
  • {??
  • ????//向Binder驅動發送BINDER_SET_CONTEXT_MGR的消息??
  • ????return?ioctl(bs->fd,?<span?style="color:#ff0000;">BINDER_SET_CONTEXT_MGR</span>,?0);??
  • }??
  • ? ? 我們看到,當ServiceManager向Binder驅動發送BINDER_SET_CONTEXT_MGR的消息時,Binder就會把他注冊為“管理員”


    三、Service_manager服務過程

    3.1、Service_manager的執行流程

    ? ? ? ? 經過前面兩步的操作,我們不僅打開了Binder,而且把當前的ServiceManager注冊成為了管理員,下面要做的就是去承擔管理員的職責,也就是接收各種請求
    ? ? ? ? 這一步的入口是binder_loop(): [java]?view plaincopy
  • void?binder_loop(struct?binder_state?*bs,?binder_handler?func)?{??
  • ????int?res;??
  • ????struct?binder_write_read?bwr;??
  • ????unsigned?readbuf[32];??
  • ????bwr.write_size?=?0;??
  • ????bwr.write_consumed?=?0;??
  • ????bwr.write_buffer?=?0;??
  • ????readbuf[0]?=?BC_ENTER_LOOPER;??
  • ????//告訴Binder,ServiceManager將要進入LOOPER狀態了??
  • ????binder_write(bs,?readbuf,?sizeof(unsigned));??
  • ??
  • ????for?(;;)?{??
  • ????????//準備要發送的數據??
  • ????????bwr.read_size?=?sizeof(readbuf);??
  • ????????bwr.read_consumed?=?0;??
  • ????????bwr.read_buffer?=?(unsigned)?readbuf;??
  • ????????//與底層Binder通訊,得到客戶端的請求??
  • ????????res?=?<span?style="color:#ff0000;">ioctl</span>(bs->fd,?BINDER_WRITE_READ,?&bwr);??
  • ????????//用func解析請求并構建應答返回給客戶端??
  • ????????res?=?<span?style="color:#ff0000;">binder_parse</span>(bs,?0,?readbuf,?bwr.read_consumed,?<span?style="color:#ff0000;">func</span>);??
  • ????}??
  • }??
  • ? ? ? ? 上面的過程表明了Service_manager進入循環的過程,主要分為三個步驟:
    ? ? ? ? 1、先通過發送BC_ENTER_LOOPER消息告訴底層,ServiceManager將要進入循環了;
    ? ? ? ? 2、在死循環中讀取客戶端的請求;
    ? ? ? ? 3、處理請求;

    ? ? ? ? 上面的第一步是通過向Binder發送BC_ENTER_LOOPER消息實現的,第二步通過BINDER_WRITE_READ可以讀取Binder中的數據(請求);第三步需要調用binder_parse去處理客戶端的請求,我們主要看一下這個過程。

    3.2、ServiceManager處理請求并回應客戶端的過程

    ? ? ? ? ServiceManager是通過binder_parse()的函數來處理請求的: [java]?view plaincopy
  • int?binder_parse(struct?binder_state?*bs,struct?binder_io?*bio,uint32_t?*ptr,uint32_t?size,binder_handler?func){??
  • ????while?(ptr?<?end)?{??
  • ????????uint32_t?cmd?=?*ptr++;??
  • ????????switch(cmd)?{??
  • ????????????case?BR_NOOP:??
  • ????????????case?BR_TRANSACTION_COMPLETE:??
  • ????????????case?BR_INCREFS:??
  • ????????????case?BR_ACQUIRE:??
  • ????????????case?BR_RELEASE:??
  • ????????????case?BR_DECREFS:??
  • ????????????????break;??
  • ????????????<span?style="color:#ff0000;">case?BR_TRANSACTION</span>:?{??
  • ????????????????struct?binder_txn?*txn?=?(void?*)?ptr;??
  • ????????????????binder_dump_txn(txn);??
  • ????????????????if?(func)?{??
  • ????????????????????unsigned?rdata[256/4];??
  • ????????????????????struct?binder_io?msg;??
  • ????????????????????struct?binder_io?reply;??
  • ????????????????????bio_init(&reply,?rdata,?sizeof(rdata),?4);??
  • ????????????????????bio_init_from_txn(&msg,?txn);??
  • ????????????????????//調用service_manager.c中的svcmgr_handler去處理數據??
  • ????????????????????res?=?func(bs,?txn,?&msg,?&reply);??
  • ????????????????????//將Service_manager對客戶端的回應數據(reply)返回給Binder驅動??
  • ????????????????????binder_send_reply(bs,?&reply,?txn->data,?res);??
  • ????????????????}??
  • ????????????????ptr?+=?sizeof(*txn)?/?sizeof(uint32_t);??
  • ????????????????break;??
  • ????????????}??
  • ????????????case?BR_REPLY:???
  • ????????????case?BR_DEAD_BINDER:???
  • ????????????case?BR_FAILED_REPLY:??
  • ????????????case?BR_DEAD_REPLY:??
  • ????????????default:??
  • ????????}??
  • ????}??
  • ????return?r;??
  • }??
  • ? ? ? ? 這個函數中我們只關心BR_TRANSACTION分支,通過調用func去解析拿到的請求,然后把返回值作為回應通過binder_send_reply()函數返回給客戶端。

    3.2.1、處理請求過程

    ? ? ? ? 我們先來看一下請求的處理過程,也就是func()的流程,這里的func來自于調用binder_loop()時的參數: [java]?view plaincopy
  • binder_loop(bs,?svcmgr_handler);??
  • ? ? ? ? 因此func()就是svcmgr_handler(): [java]?view plaincopy
  • int?svcmgr_handler(struct?binder_state?*bs,struct?binder_txn?*txn,struct?binder_io?*msg,struct?binder_io?*reply){??
  • ????switch(txn->code)?{??
  • ????????case?SVC_MGR_GET_SERVICE:??
  • ????????case?SVC_MGR_CHECK_SERVICE:??
  • ????????????//得到一個Service??
  • ????????????s?=?bio_get_string16(msg,?&len);??
  • ????????????ptr?=?do_find_service(bs,?s,?len,?txn->sender_euid);??
  • ????????????bio_put_ref(reply,?ptr);??
  • ????????????return?0;??
  • ??
  • ????????case?SVC_MGR_ADD_SERVICE:??
  • ????????????//添加一個Service??
  • ????????????s?=?bio_get_string16(msg,?&len);??
  • ????????????ptr?=?bio_get_ref(msg);??
  • ????????????allow_isolated?=?bio_get_uint32(msg)???1?:?0;??
  • ????????????if?(do_add_service(bs,?s,?len,?ptr,?txn->sender_euid,?allow_isolated))??
  • ????????????????return?-1;??
  • ????????????break;??
  • ??
  • ????????case?SVC_MGR_LIST_SERVICES:?{??
  • ????????????//得到當前所有的Service??
  • ????????????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;??
  • ????????}??
  • ????}??
  • ????return?0;??
  • }??
  • ? ? ? ? 從svcmgr_handler的case分支我們可以看出,作為Service_manager主要完成三個功能:
    ? ? ? ? 1、得到一個Service;
    ? ? ? ? 2、添加一個Service;
    ? ? ? ? 3、列出所有的Service;

    ? ? ? ? 下面我們分別看一下這三個功能的實現方式,我們先從add一個Service開始: [java]?view plaincopy
  • int?do_add_service(struct?binder_state?*bs,uint16_t?*s,unsigned?len,void?*ptr,unsigned?uid,int?allow_isolated)?{??
  • ????struct?svcinfo?*si;??
  • ????//檢查當前注冊的Service的uid和注冊的服務名稱是否有權限??
  • ????if?(!svc_can_register(uid,?s))?{??
  • ????????return?-1;??
  • ????}??
  • ????//查看是否已經add過了??
  • ????si?=?find_svc(s,?len);??
  • ????if?(si)?{??
  • ????????if?(si->ptr)?{??
  • ????????????svcinfo_death(bs,?si);??
  • ????????}??
  • ????????si->ptr?=?ptr;??
  • ????}?else?{??
  • ????????si?=?malloc(sizeof(*si)?+?(len?+?1)?*?sizeof(uint16_t));??
  • ????????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->allow_isolated?=?allow_isolated;??
  • ????????si->next?=?svclist;??
  • ????????//把當前需要注冊的Service添加到svclist中,完成注冊過程??
  • ????????svclist?=?si;??
  • ????}??
  • }??
  • ? ? ? ? 從add的過程可以看出,所謂向ServiceManager注冊一個服務,其實就是為當前的Service創建svcinfo的結構體,并把該結構體添加到svclist中
    ? ? ? ? 那么我們可以推測,find的過程無非就是去svclist中查找svcinfo的過程: [java]?view plaincopy
  • void?*do_find_service(struct?binder_state?*bs,?uint16_t?*s,?unsigned?len,?unsigned?uid)?{??
  • ????struct?svcinfo?*si;??
  • ????//從svclist鏈表中得到當前請求的Service信息??
  • ????si?=?find_svc(s,?len);??
  • ????if?(si?&&?si->ptr)?{??
  • ????????//得到一個Service需要這個Service的許可??
  • ????????if?(!si->allow_isolated)?{??
  • ????????????//還要檢查申請者的uid是否匹配??
  • ????????????unsigned?appid?=?uid?%?AID_USER;??
  • ????????????if?(appid?>=?AID_ISOLATED_START?&&?appid?<=?AID_ISOLATED_END)?{??
  • ????????????????return?0;??
  • ????????????}??
  • ????????}??
  • ????????return?si->ptr;??
  • ????}?else?{??
  • ????????return?0;??
  • ????}??
  • }??
  • ? ? ? ? 這個過程確實如我們所料,需要通過find_svc()在svclist中尋找需要的Service并把該Service節點發送給請求的Client。
    ? ? ? ? 那么list Service的請求只需要把svclist返回給Client即可:

    [java]?view plaincopy
  • case?SVC_MGR_LIST_SERVICES:?{??
  • ????unsigned?n?=?bio_get_uint32(msg);??
  • ??
  • ????si?=?svclist;??
  • ????while?((n--?>?0)?&&?si)??
  • ????????si?=?si->next;??
  • ????if?(si)?{??
  • ????????//把svclist返回給請求者??
  • ????????bio_put_string16(reply,?si->name);??
  • ????????return?0;??
  • ????}??
  • ????return?-1;??
  • }??
  • ? ? ? ? 經過這些過程,ServiceManager就完成了解析數據的過程,下面就需要把相應的數據返回給客戶端。

    3.2.2、回應客戶端的過程

    ? ? ? ? 在3.2.1中的三個請求處理過程中,特別是get和list Service的請求,最終都需要給客戶端相應回應的,我們看到在這兩個請求的處理最后,都將相應的回應數據放入了reply的指針中,當從svcmgr_handler()返回后,就把數據帶到了binder_parse()中,我們再來回顧一下這里的代碼: [java]?view plaincopy
  • int?binder_parse(struct?binder_state?*bs,struct?binder_io?*bio,uint32_t?*ptr,uint32_t?size,binder_handler?func){??
  • ????while?(ptr?<?end)?{??
  • ????????switch(cmd)?{??
  • ????????????case?BR_TRANSACTION:?{??
  • ????????????????struct?binder_txn?*txn?=?(void?*)?ptr;??
  • ????????????????binder_dump_txn(txn);??
  • ????????????????if?(func)?{??
  • ????????????????????//reply就是svcmgr_handler()中得到的回應??
  • ????????????????????res?=?func(bs,?txn,?&msg,?&reply);??
  • ????????????????????//將回應數據(reply)返回給Binder驅動??
  • ????????????????????binder_send_reply(bs,?&reply,?txn->data,?res);??
  • ????????????????}??
  • ????????????????ptr?+=?sizeof(*txn)?/?sizeof(uint32_t);??
  • ????????????????break;??
  • ????????????}??
  • ????????}??
  • ????}??
  • ????return?r;??
  • }??
  • ? ? ? ? 在binder_parse()中又調用binder_send_reply()函數完成回應的操作: [java]?view plaincopy
  • void?binder_send_reply(struct?binder_state?*bs,?struct?binder_io?*reply,?void?*buffer_to_free,?int?status)?{??
  • ????struct?{??
  • ????????uint32_t?cmd_free;??
  • ????????void?*buffer;??
  • ????????uint32_t?cmd_reply;??
  • ????????struct?binder_txn?txn;??
  • ????}?__attribute__((packed))?data;??
  • ??
  • ????data.cmd_free?=?BC_FREE_BUFFER;??
  • ????data.buffer?=?buffer_to_free;??
  • ????data.cmd_reply?=?BC_REPLY;??
  • ????data.txn.target?=?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.offs_size?=?0;??
  • ????????data.txn.data?=?&status;??
  • ????????data.txn.offs?=?0;??
  • ????}?else?{??
  • ????????data.txn.flags?=?0;??
  • ????????data.txn.data_size?=?reply->data?-?reply->data0;??
  • ????????data.txn.offs_size?=?((char*)?reply->offs)?-?((char*)?reply->offs0);??
  • ????????data.txn.data?=?reply->data0;??
  • ????????data.txn.offs?=?reply->offs0;??
  • ????}??
  • ????//向Binder寫回應的數據??
  • ????binder_write(bs,?&data,?sizeof(data));??
  • }??
  • ? ? ? ? 在給Binder發送返回值時,構建了data的數據,并把reply放入其中,并標記了數據的大小,最后通過binder_write()函數將數據寫到Binder中,而且寫的方法仍然是調用ioctl()。 [java]?view plaincopy
  • int?binder_write(struct?binder_state?*bs,?void?*data,?unsigned?len)?{??
  • ????struct?binder_write_read?bwr;??
  • ????int?res;??
  • ????bwr.write_size?=?len;??
  • ????bwr.write_consumed?=?0;??
  • ????bwr.write_buffer?=?(unsigned)?data;??
  • ????bwr.read_size?=?0;??
  • ????bwr.read_consumed?=?0;??
  • ????bwr.read_buffer?=?0;??
  • ????//向Binder寫數據??
  • ????res?=?ioctl(bs->fd,?BINDER_WRITE_READ,?&bwr);??
  • ????if?(res?<?0)?{??
  • ????????fprintf(stderr,"binder_write:?ioctl?failed?(%s)\n",?strerror(errno));??
  • ????}??
  • ????return?res;??
  • }??
  • ? ? ? ? 經過以上步驟,就完成了一次完整的請求調用過程。


    四、總結

    ? ? ? ? 我們用兩張圖來總結ServiceManager提供服務的過程。

    4.1、ServiceManager初始化流程



    4.2、ServiceManager處理事務的流程



    原文地址:http://blog.csdn.net/u010961631/article/details/19838637

    總結

    以上是生活随笔為你收集整理的Binder源码分析之ServiceManager(原)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。