美文网首页Binder进程间通信
Binder进程通信之DNS

Binder进程通信之DNS

作者: 世界的尽头是编制 | 来源:发表于2019-05-23 13:47 被阅读0次
    Binder进程通信中的DNS -----ServiceManager

    如同互联网中的"DNS"需要在浏览各种网页之前就必须准备就绪,同样ServiceManager也需要有人使用Binder之前就必须处于正常状态。

    接下来我们简单介绍ServiceManager。

    1.何时启动

    既然需要有人在使用Binder之前就需要准备就绪,那么很自然的就会想到Android系统上电init进程起来之后解析init.rc时候启动的,事实证明的确如此。
    system/core/rootdir/init.rc

    service servicemanager /system/bin/servicemanager
        class core
        user system
        group system
        critical
        onrestart restart healthd
        onrestart restart zygote
        onrestart restart media
        onrestart restart surfaceflinger
        onrestart restart drm
    
    

    从上面的代码可以知道,如果servicemanager遇到问题重启后,healthd、zygote、media、surfaceflinger、drm也会跟着重启。

    2.ServiceManager源码在哪儿
    frameworks\native\cmds\servicemanager
    
    
    3.启动之后主要负责什么工作
    int main(int argc, char **argv)
    {
        struct binder_state *bs;
    
        bs = binder_open(128*1024);//打开Binder设备
        if (!bs) {
            ALOGE("failed to open binder driver\n");
            return -1;
        }
    
        if (binder_become_context_manager(bs)) {//将自己设置成Binder大管家,整个Android只允许一个servicemanager存在
            ALOGE("cannot become context manager (%s)\n", strerror(errno));
            return -1;
        }
    
        selinux_enabled = is_selinux_enabled();
        sehandle = selinux_android_service_context_handle();
        selinux_status_open(true);
    
        if (selinux_enabled > 0) {
            if (sehandle == NULL) {
                ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
                abort();
            }
    
            if (getcon(&service_manager_context) != 0) {
                ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
                abort();
            }
        }
    
        union selinux_callback cb;
        cb.func_audit = audit_callback;
        selinux_set_callback(SELINUX_CB_AUDIT, cb);
        cb.func_log = selinux_log_callback;
        selinux_set_callback(SELINUX_CB_LOG, cb);
    
        binder_loop(bs, svcmgr_handler);//进入loop循环,等待用户请求
    
        return 0;
    }
    
    

    从上述代码知道,main函数主要做了如下几件事:

    1>打开Binder设备

    frameworks\native\cmds\servicemanager\binder.c

    struct binder_state *binder_open(size_t mapsize)
    {
        struct binder_state *bs;
        struct binder_version vers;
    
        bs = malloc(sizeof(*bs));
        if (!bs) {
            errno = ENOMEM;
            return NULL;
        }
    
        bs->fd = open("/dev/binder", O_RDWR);//打开Binder驱动节点
        if (bs->fd < 0) {
            fprintf(stderr,"binder: cannot open device (%s)\n",
                    strerror(errno));
            goto fail_open;
        }
    
        if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
            (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
            fprintf(stderr,
                    "binder: kernel driver version (%d) differs from user space version (%d)\n",
                    vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
            goto fail_open;
        }
    
        bs->mapsize = mapsize;
        bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
        if (bs->mapped == MAP_FAILED) {
            fprintf(stderr,"binder: cannot map device (%s)\n",
                    strerror(errno));
            goto fail_map;
        }
    
        return bs;
    
    fail_map:
        close(bs->fd);
    fail_open:
        free(bs);
        return NULL;
    }
    
    
    2>将自己设置成Binder大管家

    frameworks\native\cmds\servicemanager\binder.c

    int binder_become_context_manager(struct binder_state *bs)
    {
        return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
    }
    
    
    3>进入主循环

    frameworks\native\cmds\servicemanager\binder.c

    void binder_loop(struct binder_state *bs, binder_handler func)
    {
        int res;
        struct binder_write_read bwr;
        uint32_t readbuf[32];
    
        bwr.write_size = 0;
        bwr.write_consumed = 0;
        bwr.write_buffer = 0;
    
        readbuf[0] = BC_ENTER_LOOPER;
        binder_write(bs, readbuf, sizeof(uint32_t));//往Binder写入信息
    
        for (;;) {
            bwr.read_size = sizeof(readbuf);
            bwr.read_consumed = 0;
            bwr.read_buffer = (uintptr_t) readbuf;
    
            res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//从Binder读取消息
    
            if (res < 0) {
                ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
                break;
            }
    
            res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);//处理这条消息
            if (res == 0) {
                ALOGE("binder_loop: unexpected reply?!\n");
                break;
            }
            if (res < 0) {
                ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
                break;
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:Binder进程通信之DNS

        本文链接:https://www.haomeiwen.com/subject/gzvvzqtx.html