美文网首页framework学习笔记
framework 学习笔记6. ServiceManager进

framework 学习笔记6. ServiceManager进

作者: 加个标志位 | 来源:发表于2020-12-09 09:30 被阅读0次

    一. ServiceManager进程是init进程解析init.rc启动的第一个服务进程,涉及到的源代码有framework/native/cmd/servicemanager目录下的 service_manager.c和binder.c ,这里的binder.c并不是binder驱动代码,而属于native层的代码;
    首先进入main()方法,一共分三步:
    a. 打开binder驱动;
    b. 成为binder驱动管理者;
    c. 循环等待处理client请求;
    这三步对应的调用了framework/native/cmd/servicemanager包下的binder.c中的三个方法,详情如下:

    int main(int argc, char **argv){
        struct binder_state *bs;
        bs = binder_open(128*1024);  //a打开binder驱动;
        if (!bs) {
            ALOGE("failed to open binder driver\n");
            return -1;
        }
        if (binder_become_context_manager(bs)) {  //成为binder驱动管理者;
            ALOGE("cannot become context manager (%s)\n", strerror(errno));
            return -1;
        }
        selinux_enabled = is_selinux_enabled();
        sehandle = selinux_android_service_context_handle();
        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);
        svcmgr_handle = BINDER_SERVICE_MANAGER;
        binder_loop(bs, svcmgr_handler);  //c循环等待处理client请求;
    
        return 0;
    }
    
    
    1. 打开Binder驱动:binder_open(128*1024),大小为128kb;
    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;
        }
        //打开驱动,调用的是驱动层的binder_open()
        bs->fd = open("/dev/binder", O_RDWR);
        if (bs->fd < 0) {
            fprintf(stderr,"binder: cannot open device (%s)\n",
                    strerror(errno));
            goto fail_open;
        }
        // 获取binder驱动的版本,ioctl()==>binder_ioctl()
        if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
            (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
            fprintf(stderr, "binder: driver version differs from user space\n");
            goto fail_open;
        }
        //调用的是驱动层的binder_mmap()
        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;
    }
    
    
    1. 成为binder驱动管理者:binder_become_context_manager()
    // 通知驱动,当前进程成为驱动层的管理者,调用的也是binder_ioctl();
    int binder_become_context_manager(struct binder_state *bs){
        return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
    }
    
    1. 循环等待处理client请求
    void binder_loop(struct binder_state *bs, binder_handler func){
        int res;
        struct binder_write_read bwr; //这个结构体在笔记5中有说明
        uint32_t readbuf[32];
        bwr.write_size = 0;
        bwr.write_consumed = 0;
        bwr.write_buffer = 0;
        readbuf[0] = BC_ENTER_LOOPER;   // BC_ENTER_LOOPER指令
        binder_write(bs, readbuf, sizeof(uint32_t));  //见3.1
    
        for (;;) {  //这是一共死循环---核心代码 
            bwr.read_size = sizeof(readbuf);
            bwr.read_consumed = 0;
            bwr.read_buffer = (uintptr_t) readbuf;
            //会进入等待,如果有别的进程通过binder_ioctl()写入了数据,这里就会唤醒;
            res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    
            if (res < 0) {
                ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
                break;
            }
            //获取到数据后,进行解析  3.2
            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;
            }
        }
    }
    

    3.1 framework/native/cmd/servicemanager/binder.c中的binder_write(bs, readbuf, sizeof(uint32_t))方法:
    参数定义:
    a. bs = binder_open(128*1024);
    b. readbuf[0] = BC_ENTER_LOOPER;
    c. sizeof(uint32_t) 4字节;

    int binder_write(struct binder_state *bs, void *data, size_t len){
        struct binder_write_read bwr;
        int res;
        bwr.write_size = len;
        bwr.write_consumed = 0;
        bwr.write_buffer = (uintptr_t) data;
        //写入数据的时候,不需要读,read方面的全为0;驱动根据write_size>0写入,read_size>0读取;
        bwr.read_size = 0;
        bwr.read_consumed = 0;
        bwr.read_buffer = 0;
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); // ioctl()方法;
        if (res < 0) {
            fprintf(stderr,"binder_write: ioctl failed (%s)\n",
                    strerror(errno));
        }
        return res;
    }
    

    3.2 binder_parse()方法;
    uintptr_t ptr : 首地址

    int binder_parse(struct binder_state *bs, struct binder_io *bio, uintptr_t ptr, size_t size, binder_handler func){
        int r = 1;
        uintptr_t end = ptr + (uintptr_t) size;  // 根据首地址和size确定end;
    
        while (ptr < end) {
            // cmd命令,笔记5中有分析到,当然这里的命令不是原封不动的笔记5中的BC_TRANSACTION命令了,binder驱动会有一                
            //个转化===>BR_TRANSACTION
    uint32_t cmd = *(uint32_t *) ptr;    
            ptr += sizeof(uint32_t);
    
            switch(cmd) {
            case BR_NOOP:
                break;
            case BR_TRANSACTION_COMPLETE:
                break;
            case BR_INCREFS:
            case BR_ACQUIRE:
            case BR_RELEASE:
            case BR_DECREFS:
    
                ptr += sizeof(struct binder_ptr_cookie);
                break;
            case BR_TRANSACTION: {
                struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
                if ((end - ptr) < sizeof(*txn)) {
                    ALOGE("parse: txn too small!\n");
                    return -1;
                }
                binder_dump_txn(txn);
                if (func) {  //这个func是回调函数,如果有,则回调回去;
                    unsigned rdata[256/4];
                    struct binder_io msg;
                    struct binder_io reply;
                    int res;
    
                    bio_init(&reply, rdata, sizeof(rdata), 4);    // 初始化,通过binder io 来管理这一块内存;
                    bio_init_from_txn(&msg, txn);    // 数据赋值操作;
                    res = func(bs, txn, &msg, &reply);    //方法回调,真正处理业务逻辑的核心地方
                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);//发送应答数据
                }
                ptr += sizeof(*txn);
                break;
            }
            case BR_REPLY: {
                struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
                if ((end - ptr) < sizeof(*txn)) {
                    ALOGE("parse: reply too small!\n");
                    return -1;
                }
                binder_dump_txn(txn);
                if (bio) {
                    bio_init_from_txn(bio, txn);    //初始化,通过binder io 来管理这一块内存;
                    bio = 0;
                } else {
                    /* todo FREE BUFFER */
                }
                ptr += sizeof(*txn);
                r = 0;
                break;
            }
            case BR_DEAD_BINDER: {
                struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
                ptr += sizeof(binder_uintptr_t);
                death->func(bs, death->ptr);
                break;
            }
            case BR_FAILED_REPLY:
                r = -1;
                break;
            case BR_DEAD_REPLY:
                r = -1;
                break;
            default:
                ALOGE("parse: OOPS %d\n", cmd);
                return -1;
            }
        }
        return r;
    }
    

    回调方法分析

    int svcmgr_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply){
        struct svcinfo *si;
        uint16_t *s;
        size_t len;
        uint32_t handle;
        uint32_t strict_policy;
        int allow_isolated;
    
        if (txn->target.handle != svcmgr_handle)
            return -1;
    
        if (txn->code == PING_TRANSACTION)
            return 0;
    
        strict_policy = bio_get_uint32(msg);
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
    
        if ((len != (sizeof(svcmgr_id) / 2)) ||
            memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {  //svcmgr_id是android.os.iservicemanager
            fprintf(stderr,"invalid id %s\n", str8(s, len));
            return -1;  //如果不是传给iservicemanager,则返回
        }
    
        if (sehandle && selinux_status_updated() > 0) {
            struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
            if (tmp_sehandle) {
                selabel_close(sehandle);
                sehandle = tmp_sehandle;
            }
        }
    
        switch(txn->code) {
        case SVC_MGR_GET_SERVICE:
        case SVC_MGR_CHECK_SERVICE:
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
            if (!handle)
                break;
            bio_put_ref(reply, handle);
            return 0;
    
        case SVC_MGR_ADD_SERVICE:  //添加服务
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            handle = bio_get_ref(msg);
            allow_isolated = bio_get_uint32(msg) ? 1 : 0;
            //do_add_service()中的sender_pid是pid_t,用来检验权限
            if (do_add_service(bs, s, len, handle, txn->sender_euid,allow_isolated, txn->sender_pid))                                           
                return -1;
            break;
    
        case SVC_MGR_LIST_SERVICES: {
            uint32_t n = bio_get_uint32(msg);
    
            if (!svc_can_list(txn->sender_pid)) {
                ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                        txn->sender_euid);
                return -1;
            }
            si = svclist;
            while ((n-- > 0) && si)
                si = si->next;
            if (si) {
                bio_put_string16(reply, si->name);
                return 0;
            }
            return -1;
        }
        default:
            ALOGE("unknown code %d\n", txn->code);
            return -1;
        }
    
        bio_put_uint32(reply, 0);
        return 0;
    }
    
    servicemanager.PNG

    相关文章

      网友评论

        本文标题:framework 学习笔记6. ServiceManager进

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