国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

android servicemanager與binder源碼分析一 ------ native層的

馬忠志 / 790人閱讀

摘要:以版本源碼為例。源碼位于下打開驅(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)求;

binder_open

位于/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_looper
372void 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

相關(guān)文章

  • android servicemanagerbinder源碼分析三------如何進(jìn)入內(nèi)核通訊

    摘要:的構(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...

    lijy91 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<