<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ### Android 開發之serviceManager分析 在Android系統中用到最多的通信機制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驅動程序組成。其中Client、Service和ServiceManager運行在用戶空間,而Binder驅動程序運行在內核空間。核心組件就是Binder驅動程序了,而ServiceManager提供輔助管理的功能,無論是Client還是Service進行通信前首先要和ServiceManager取得聯系。而ServiceManager是一個守護進程,負責管理Server并向Client提供查詢Server的功能。 ~~~ 在init.rc中servicemanager是作為服務啟動的,而且是在zygote啟動之前 service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drm ~~~ 源碼位置:frameworks/base/cmds/servicemanager/service_manager.c ~~~ int main(int argc, char**argv) { struct binder_state *bs; void* svcmgr = BINDER_SERVICE_MANAGER; bs = binder_open(128*1024); binder_become_context_manager(bs); svcmgr_handle = svcmgr; binder_loop(bs, svcmgr_handler); return 0; } ~~~ 這里main函數主要有三個功能: 1)打開Binder設備文件 首先我們來看看這個struct binder_state結構體 ~~~ struct binder_state { ??????? int fd;???// 文件描述符,打開/dev/binder設備 ????????void* mapped;??// 把設備文件/dev/binder映射到進程空間的起始地址 ??????? unsigned mapsize;?// 映射內存空間的大小 }; ~~~ 宏:#define BINDER_SERVICE_MANAGER ((void*)0) 表示ServiceManager對應的句柄為0,表面自己是服務器管理者。其他的Server進程句柄值都是大于0的。 ~~~ struct binder_state* binder_open(unsigned mapsize) { struct binder_state* bs; bs = malloc(sizeof(*bs)); bs->fd = open("/dev/binder", O_RDWR); bs->mapsize = mapsize; bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); return bs; } 這里主要就是打開Binder設備,映射128K的內存地址空間 ~~~ 2)告訴Binder驅動程序自己是Binder上下文管理者 ~~~ int binder_become_context_manager(struct binder_state *bs) { return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); } 調用驅動程序設置這個進程為管理者BINDER_SET_CONTEXT_MGR ~~~ 3)進入一個無線循環,充當server角色,等待Client的請求 ~~~ void binder_loop(struct binder_state bs, binder_handler func) { 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; // 設置事件類型為LOOPER // 調用ioctl函數,通知Binder設備servicemanager開始進入loop狀態 binder_write(bs, readbuf, sizeof(unsigned)); for(;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; bwr.read_buffer = (unsigned)readbuf; // 進入Binder設備緩沖區,檢查是否有IPC請求 ioctl(bs->fd, BINDER_WRITE_READ, &bwr); // 對于請求調用binder_parse進行解析處理 binder_parse(bs, 0, readbuf, bwr.read_consumed, func); } } 這里我們看下struct binder_write_read這個結構體: struct binder_write_read{ signed long write_size; signed long write_consumed; // bytes consumed by driver unsigned long write_buffer; signed long read_size; signed long read_consumed; // bytes consumed by driver unsigned long read_buffer; }; int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, binder_handler func) { uint32_t *end = ptr + (size / 4); while(ptr < end) { uint32_t cmd = *ptr++; switch(cmd) { ...... case BR_TRANSACTOIN:{ // 收到請求進行處理 struct bindeer_txn *txn = (void*) ptr; 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); ret = func(bs, txn, &msg, &reply); binder_send_reply(bs, &reply, txn->data, res); } ptr += sizeof(*txn) / sizeof(uint32_t); break; } case BR_REPLY: { // 回復的請求處理 struct binder_txn *txn = (void*)ptr; if(bio) { bio_init_from_txn(bio, txn); bio = 0; }else { // to free buffer } ptr += sizeof(*txn) / sizeof(uint32_t); r = 0; break; } case BR_DEAD_BINDER: { struct binder_death* death = (void*)*ptr++; death->func(bs, death->ptr); break; } ... } } return r; } /*這里binder_parse函數首先將binder讀取過來的請求數據轉化為bindeer_txn結構體,然后根據這個結構體 初始化binder_io msg,交給回調函數svcmgr_handler處理,同時返回一個binder_io reply,最后將 這個reply發送返回給客戶端。*/ struc binder_io { char* data; // 指向read/write的數據 uint32_t *offs; // 偏移數組 uint32_t data_avail; // data中有效字節長 uint32_t offs_avail; // 偏移數組中有效字節長 char* data0; // data起始地址 uint32_t *offs0; // 偏移buffer的起始地址 uint32_t flags; uint32_t unused; }; 最終調用的處理函數還是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; if(txn->target != svcmgr_handler) return -1; // 首先判斷這個消息的是不是發給自己的 strict_policy = bio_get_uint32(msg); s = bio_get_string16(msg, &len); 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); // 根據服務名字查找鏈表 bio_put_ref(reply, ptr); return 0; case SVC_MGR_ADD_SERVICE: // 添加服務 s = bio_get_string16(msg, &len); ptr = bio_get_ref(msg); do_add_service(bs, s, len, ptr, txn->sender_euid); bio_put_uint32(reply, 0); // 告知添加成功 return 0; .... } return 0; } ~~~ 首先我們得看看Binder是怎么組織Binder傳遞消息的數據結構的,根據前面我們知道調用Binder驅動 的時候我們獲得了一個void * ptr結構體,強制轉化為binder_txn * txn,然后根據這個txn我們獲得了 Binder的輸入輸出結構體binder_io * bio。最后我們不管是處理請求還是發送回復都是處理這個bio結構。 而我們的Binder通信的binder結構是由binder_object來組織的,指向binder_io結構里面data。 首先我們得看看Binder是怎么組織Binder傳遞消息的數據結構的,根據前面我們知道調用Binder驅動 的時候我們獲得了一個void* ptr結構體,強制轉化為binder_txn * txn,然后根據這個txn我們獲得了 Binder的輸入輸出結構體binder_io * bio。最后我們不管是處理請求還是發送回復都是處理這個bio結構。 而我們的Binder通信的binder結構是由binder_object來組織的,指向binder_io結構里面data。 ~~~ struct binder_object { uint32_t type; uint32_t flags; void* pointer; void* cookie; }; ~~~ 上面的binder_object結構體內容依次對應著我們代碼中的: bio_get_uint32(msg); bio_get_string16(msg, &len); bio_get_string16(msg, &len); bio_get_ref(msg); 上面的binder_object結構體內容依次對應著我們代碼中的: bio_get_uint32(msg); bio_get_string16(msg, &len); bio_get_string16(msg, &len); bio_get_ref(msg); 當客戶端需要添加服務的時候:SVC_MGR_ADD_SERVICE 1)首先調用bio_get_string16()從binder_io中獲得服務名字。 2)調用bio_get_ref()從binder_io中獲得服務的binder實體struct binder_object ~~~ void* bio_get_ref(struct binder_io* bio) { struct binder_object* obj; obj = _bio_get_obj(bio);// 這個函數最終調用的是 void* ptr = bio->data; return obj->pointer; } ~~~ 3)調用do_add_service()將上面的Binder實體引用寫到服務中,再通過名字加到全局鏈表中 ~~~ int do_add_service(struct binder_state* bs, uint16_t *s, unsigned len, void* ptr, unsigned uid) { struct svcinfo *si; svc_can_register(uid, s); // 檢查權限 si = find_svc(s, len); // 根據名字查找鏈表,判斷是否已經存在 si = malloc(sizeof(*si) + (len+1)*sizeof(uin16_t)); si->ptr = ptr; //指向上面的binder_object的pointer也就是Binder實體 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; } ~~~ 當客戶端需要查詢服務的時候: 1)bio_get_string16() 獲得服務名字 2)do_find_service() 遍歷全局鏈表svclist,根據服務名字找到對應的服務并返回。 2)bio_put_ref(reply, ptr);這里reply就是需要返回給客戶端的結構體,而ptr就是指向目標Binder實體。 ~~~ void bio_put_ref(struct binder_io* bio, void* ptr) { struct binder_object *obj; obj = bio_alloc(bio); obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; obj->type = BINDER_TYPE_HANDLE; obj->pointer = ptr; obj->cookie = 0; } ~~~ 回到binder_parse函數里面,執行:binder_send_reply()通知Binder驅動程序。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看