摘要:以版本源碼為例。源碼位于下打開驅(qū)動(dòng)設(shè)備,將自己作為的管理者,進(jìn)入循環(huán),作為等待的請(qǐng)求位于首先,建立一個(gè)結(jié)構(gòu)體,然后剩下的就是給這個(gè)結(jié)構(gòu)體的成員賦值。同屬于這一層,因此我們看看具體內(nèi)容剛才從驅(qū)動(dòng)設(shè)備讀取的的前位取出來作為進(jìn)行判斷處理。
前一陣子在忙項(xiàng)目,沒什么更新,這次開始寫點(diǎn)android源碼內(nèi)部的東西分析下。以6.0.1_r10版本android源碼為例。
servicemanager是android服務(wù)管理,非常基礎(chǔ)的組件之一,分析他的目的是能夠深入看到binder的一些處理方式。在開始前先說下閱讀源碼或者非常復(fù)雜代碼的方式,我的方式是層級(jí)進(jìn)入,一層掌握脈絡(luò)之后如果感興趣再對(duì)具體的點(diǎn)深入分析了解,并且每層進(jìn)行總結(jié),這樣我認(rèn)為會(huì)比較好理解,也不容易產(chǎn)生一個(gè)點(diǎn)一直走下去,最后迷失在復(fù)雜繁瑣的代碼里的情況。當(dāng)然我只代表我個(gè)人的體驗(yàn)。東西是寫給自己的,如果能幫到他人我會(huì)非常高興。
然后這里推薦下羅升陽先生的博客文章,確實(shí)非常不錯(cuò),可以作為閱讀參考。
servicemanager源碼位于/frameworks/native/cmds/servicemanager/service_manager.c下:
347int main(int argc, char **argv) 348{ 349 struct binder_state *bs; 350 351 bs = binder_open(128*1024); 352 if (!bs) { 353 ALOGE("failed to open binder driver "); 354 return -1; 355 } 356 357 if (binder_become_context_manager(bs)) { 358 ALOGE("cannot become context manager (%s) ", strerror(errno)); 359 return -1; 360 } 361 362 selinux_enabled = is_selinux_enabled(); 363 sehandle = selinux_android_service_context_handle(); 364 selinux_status_open(true); 365 366 if (selinux_enabled > 0) { 367 if (sehandle == NULL) { 368 ALOGE("SELinux: Failed to acquire sehandle. Aborting. "); 369 abort(); 370 } 371 372 if (getcon(&service_manager_context) != 0) { 373 ALOGE("SELinux: Failed to acquire service_manager context. Aborting. "); 374 abort(); 375 } 376 } 377 378 union selinux_callback cb; 379 cb.func_audit = audit_callback; 380 selinux_set_callback(SELINUX_CB_AUDIT, cb); 381 cb.func_log = selinux_log_callback; 382 selinux_set_callback(SELINUX_CB_LOG, cb); 383 384 binder_loop(bs, svcmgr_handler); 385 386 return 0; 387}
1.binder_open打開binder驅(qū)動(dòng)設(shè)備;
2.binder_become_context_manager(bs),將自己作為binder的管理者;
3.binder_loop(bs, svcmgr_handler),進(jìn)入循環(huán),作為server等待client的請(qǐng)求;
位于/frameworks/native/cmds/servicemanager/binder.c:
96struct binder_state *binder_open(size_t mapsize) 97{ 98 struct binder_state *bs; 99 struct binder_version vers; 100 101 bs = malloc(sizeof(*bs)); 102 if (!bs) { 103 errno = ENOMEM; 104 return NULL; 105 } 106 107 bs->fd = open("/dev/binder", O_RDWR); 108 if (bs->fd < 0) { 109 fprintf(stderr,"binder: cannot open device (%s) ", 110 strerror(errno)); 111 goto fail_open; 112 } 113 114 if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) || 115 (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) { 116 fprintf(stderr, 117 "binder: kernel driver version (%d) differs from user space version (%d) ", 118 vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION); 119 goto fail_open; 120 } 121 122 bs->mapsize = mapsize; 123 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); 124 if (bs->mapped == MAP_FAILED) { 125 fprintf(stderr,"binder: cannot map device (%s) ", 126 strerror(errno)); 127 goto fail_map; 128 } 129 130 return bs; 131 132fail_map: 133 close(bs->fd); 134fail_open: 135 free(bs); 136 return NULL; 137}
首先,建立一個(gè)結(jié)構(gòu)體binder_state,然后剩下的就是給這個(gè)結(jié)構(gòu)體的成員賦值。bs->fd給打開的驅(qū)動(dòng)設(shè)備文件描述符;bs->mapped給內(nèi)存映射地址;
插一句,這里對(duì)goto的應(yīng)用很規(guī)范,可見任何語句并非有好與不好,而在于怎么用。
看到這里其實(shí)可以猜測,binder的機(jī)制就是內(nèi)存映射,或者可以說是文件映射,因?yàn)樵趌inux上任何的設(shè)備都可以看做是文件。
現(xiàn)在不要深入,往回看,之前的service_manager.c的main函數(shù)里,后面就要走binder_become_context_manager這個(gè)將自己設(shè)為binder管理者。
146int binder_become_context_manager(struct binder_state *bs) 147{ 148 return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); 149}
這里就做了一件事兒,就是下發(fā)控制字,告訴驅(qū)動(dòng)設(shè)置context管理者為0,這里也可以猜測,這個(gè)0代表一定含義,應(yīng)該就是servicemanager自己,后面再繼續(xù)解釋這個(gè)問題。
binder_looper372void binder_loop(struct binder_state *bs, binder_handler func) 373{ 374 int res; 375 struct binder_write_read bwr; 376 uint32_t readbuf[32]; 377 378 bwr.write_size = 0; 379 bwr.write_consumed = 0; 380 bwr.write_buffer = 0; 381 382 readbuf[0] = BC_ENTER_LOOPER; 383 binder_write(bs, readbuf, sizeof(uint32_t)); 384 385 for (;;) { 386 bwr.read_size = sizeof(readbuf); 387 bwr.read_consumed = 0; 388 bwr.read_buffer = (uintptr_t) readbuf; 389 390 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 391 392 if (res < 0) { 393 ALOGE("binder_loop: ioctl failed (%s) ", strerror(errno)); 394 break; 395 } 396 397 res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); 398 if (res == 0) { 399 ALOGE("binder_loop: unexpected reply?! "); 400 break; 401 } 402 if (res < 0) { 403 ALOGE("binder_loop: io error %d %s ", res, strerror(errno)); 404 break; 405 } 406 }
1.先通過binder_write下發(fā)了一個(gè)BC_ENTER_LOOPER控制字,表示要驅(qū)動(dòng)設(shè)備進(jìn)入looper狀態(tài)(binder_write內(nèi)部也是走的ioctrl BINDER_WRITE_READ寫入驅(qū)動(dòng)設(shè)備);
2.進(jìn)入死循環(huán),不停從設(shè)備讀取數(shù)據(jù),成功讀取到之后,進(jìn)入binder_parse函數(shù);
3.binder_parse,從字面看是解析binder,但是具體做什么不清楚,只能猜測是對(duì)剛才讀取到的內(nèi)容進(jìn)行處理。
同屬于binder.c這一層,因此我們看看binder_parse具體內(nèi)容:
204int binder_parse(struct binder_state *bs, struct binder_io *bio, 205 uintptr_t ptr, size_t size, binder_handler func) 206{ 207 int r = 1; 208 uintptr_t end = ptr + (uintptr_t) size; 209 210 while (ptr < end) { 211 uint32_t cmd = *(uint32_t *) ptr; 212 ptr += sizeof(uint32_t); 213#if TRACE 214 fprintf(stderr,"%s: ", cmd_name(cmd)); 215#endif 216 switch(cmd) { 217 case BR_NOOP: 218 break; 219 case BR_TRANSACTION_COMPLETE: 220 break; 221 case BR_INCREFS: 222 case BR_ACQUIRE: 223 case BR_RELEASE: 224 case BR_DECREFS: 225#if TRACE 226 fprintf(stderr," %p, %p ", (void *)ptr, (void *)(ptr + sizeof(void *))); 227#endif 228 ptr += sizeof(struct binder_ptr_cookie); 229 break; 230 case BR_TRANSACTION: { 231 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; 232 if ((end - ptr) < sizeof(*txn)) { 233 ALOGE("parse: txn too small! "); 234 return -1; 235 } 236 binder_dump_txn(txn); 237 if (func) { 238 unsigned rdata[256/4]; 239 struct binder_io msg; 240 struct binder_io reply; 241 int res; 242 243 bio_init(&reply, rdata, sizeof(rdata), 4); 244 bio_init_from_txn(&msg, txn); 245 res = func(bs, txn, &msg, &reply); 246 binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); 247 } 248 ptr += sizeof(*txn); 249 break; 250 } 251 case BR_REPLY: { 252 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; 253 if ((end - ptr) < sizeof(*txn)) { 254 ALOGE("parse: reply too small! "); 255 return -1; 256 } 257 binder_dump_txn(txn); 258 if (bio) { 259 bio_init_from_txn(bio, txn); 260 bio = 0; 261 } else { 262 /* todo FREE BUFFER */ 263 } 264 ptr += sizeof(*txn); 265 r = 0; 266 break; 267 } 268 case BR_DEAD_BINDER: { 269 struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr; 270 ptr += sizeof(binder_uintptr_t); 271 death->func(bs, death->ptr); 272 break; 273 } 274 case BR_FAILED_REPLY: 275 r = -1; 276 break; 277 case BR_DEAD_REPLY: 278 r = -1; 279 break; 280 default: 281 ALOGE("parse: OOPS %d ", cmd); 282 return -1; 283 } 284 } 285 286 return r; 287}
剛才從驅(qū)動(dòng)設(shè)備讀取的buffer的前32位取出來作為cmd進(jìn)行switch判斷處理。BR_代表從設(shè)備驅(qū)動(dòng)反饋的命令,BR_TRANSACTION字面看是交易,那么可以猜測是對(duì)接受到的發(fā)送方(client)的內(nèi)容進(jìn)行處理。往下看,BR_TRANSACTION流程里,先把收到的數(shù)據(jù)轉(zhuǎn)成binder_transaction_data結(jié)構(gòu),然后走了binder_dump_txn,這里基本上就是輸出一些信息,不太關(guān)注。之后是關(guān)鍵的部分,調(diào)用了func,這個(gè)東西是個(gè)binder_handler,其實(shí)看看定義就知道,是個(gè)回調(diào)函數(shù),回到servicemanager里面的main,可以看到是個(gè)svcmgr_handler,具體內(nèi)容也在servicemanager里面,如下:
244int svcmgr_handler(struct binder_state *bs, 245 struct binder_transaction_data *txn, 246 struct binder_io *msg, 247 struct binder_io *reply) 248{ 249 struct svcinfo *si; 250 uint16_t *s; 251 size_t len; 252 uint32_t handle; 253 uint32_t strict_policy; 254 int allow_isolated; 255 256 //ALOGI("target=%p code=%d pid=%d uid=%d ", 257 // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid); 258 259 if (txn->target.ptr != BINDER_SERVICE_MANAGER) 260 return -1; 261 262 if (txn->code == PING_TRANSACTION) 263 return 0; 264 265 // Equivalent to Parcel::enforceInterface(), reading the RPC 266 // header with the strict mode policy mask and the interface name. 267 // Note that we ignore the strict_policy and don"t propagate it 268 // further (since we do no outbound RPCs anyway). 269 strict_policy = bio_get_uint32(msg); 270 s = bio_get_string16(msg, &len); 271 if (s == NULL) { 272 return -1; 273 } 274 275 if ((len != (sizeof(svcmgr_id) / 2)) || 276 memcmp(svcmgr_id, s, sizeof(svcmgr_id))) { 277 fprintf(stderr,"invalid id %s ", str8(s, len)); 278 return -1; 279 } 280 281 if (sehandle && selinux_status_updated() > 0) { 282 struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle(); 283 if (tmp_sehandle) { 284 selabel_close(sehandle); 285 sehandle = tmp_sehandle; 286 } 287 } 288 289 switch(txn->code) { 290 case SVC_MGR_GET_SERVICE: 291 case SVC_MGR_CHECK_SERVICE: 292 s = bio_get_string16(msg, &len); 293 if (s == NULL) { 294 return -1; 295 } 296 handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); 297 if (!handle) 298 break; 299 bio_put_ref(reply, handle); 300 return 0; 301 302 case SVC_MGR_ADD_SERVICE: 303 s = bio_get_string16(msg, &len); 304 if (s == NULL) { 305 return -1; 306 } 307 handle = bio_get_ref(msg); 308 allow_isolated = bio_get_uint32(msg) ? 1 : 0; 309 if (do_add_service(bs, s, len, handle, txn->sender_euid, 310 allow_isolated, txn->sender_pid)) 311 return -1; 312 break; 313 314 case SVC_MGR_LIST_SERVICES: { 315 uint32_t n = bio_get_uint32(msg); 316 317 if (!svc_can_list(txn->sender_pid)) { 318 ALOGE("list_service() uid=%d - PERMISSION DENIED ", 319 txn->sender_euid); 320 return -1; 321 } 322 si = svclist; 323 while ((n-- > 0) && si) 324 si = si->next; 325 if (si) { 326 bio_put_string16(reply, si->name); 327 return 0; 328 } 329 return -1; 330 } 331 default: 332 ALOGE("unknown code %d ", txn->code); 333 return -1; 334 } 335 336 bio_put_uint32(reply, 0); 337 return 0; 338}
簡單看下,就是對(duì)傳遞的數(shù)據(jù)的具體處理,包括了addservice等具體的過程處理。暫時(shí)先不深究。
至此我們可以看出來,servicemanager->binder.c這層基本上就是servicemanager提供系統(tǒng)的服務(wù)管理,binder.c提供對(duì)驅(qū)動(dòng)設(shè)備的操作api。整個(gè)過程再梳理下:
1.打開binder驅(qū)動(dòng)設(shè)備;
2.將自己作為binder上下文的管理者,通過binder.c傳遞0給設(shè)備驅(qū)動(dòng)(ioctrl);
3.進(jìn)入binder_looper循環(huán),不停從binder設(shè)備驅(qū)動(dòng)讀取內(nèi)容,并解析,然后根據(jù)cmd判斷后拋給servicemanager進(jìn)行真正處理;
4.servicemanager里再根據(jù)讀取到的數(shù)據(jù)內(nèi)容來決定進(jìn)行各種cmd動(dòng)作的處理,包括addservice等;
這么看這一層的脈絡(luò)基本上比較清晰了。這么寫把binder獨(dú)立了出來作為一個(gè)api層,可以搭載任何的生成調(diào)用,也就是說binder.c這一層只管與binder設(shè)備驅(qū)動(dòng)通訊,其余的拋給調(diào)用者,很標(biāo)準(zhǔn)聰明的解耦。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/65009.html
摘要:的構(gòu)造傳遞進(jìn)入的就是。如果狀態(tài)是,直接返回。到底是否正確呢看代碼先創(chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象是個(gè)存儲(chǔ)讀寫內(nèi)容的對(duì)象。然后終于進(jìn)入了內(nèi)核驅(qū)動(dòng)的部分。 承接上文,從getService開始,要開始走binder的通訊機(jī)制了。首先是上文的java層 /frameworks/base/core/java/android/os/ServiceManagerNative.java: 118 pu...
閱讀 2751·2021-11-19 09:40
閱讀 5318·2021-09-27 14:10
閱讀 2106·2021-09-04 16:45
閱讀 1473·2021-07-25 21:37
閱讀 3001·2019-08-30 10:57
閱讀 2987·2019-08-28 17:59
閱讀 1060·2019-08-26 13:46
閱讀 1413·2019-08-26 13:27