zoukankan      html  css  js  c++  java
  • i.mx6 Android5.1.1 servicemanager本地服务

    接在之前的

    i.mx6 Android5.1.1 初始化流程之init进程

    i.mx6 Android5.1.1 初始化流程之init.rc解析

    servicemanager是由init创建的本地服务,是binder的守护进程。

    主要用来管理开发者创建的各种Server,并且向Client提供查询Server远程接口的功能。

    #名字为servicemanager的服务,可执行文件的路径在/system/bin/servicemanager
    #属于core类,用户为:system,用户组为:system
    #critical:如果在几分钟内一直没响应则重启服务
    #重启servicemanager需要冲入如下的服务healthd,zygote,media,surfaceflinger,drm
    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

    可以得知其路径在/system/bin/servicemanager

    查看android.mk

    include $(CLEAR_VARS)
    LOCAL_SHARED_LIBRARIES := liblog libselinux
    LOCAL_SRC_FILES := service_manager.c binder.c
    LOCAL_CFLAGS += $(svc_c_flags)
    LOCAL_MODULE := servicemanager
    include $(BUILD_EXECUTABLE)

    可以得知,就是在service_manager.c

    int main(int argc, char **argv)
    {
        struct binder_state *bs;
        
        //打开binder设备驱动文件,并将Binder设备文件映射到servicemanger进程的地址空间中 
        bs = binder_open(128*1024);
        if (!bs) {
            ALOGE("failed to open binder driver
    ");
            return -1;
        }
        
        //在binder驱动层设置服务管理者角色  
        if (binder_become_context_manager(bs)) {
            ALOGE("cannot become context manager (%s)
    ", 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.
    ");
                abort();
            }
    
            if (getcon(&service_manager_context) != 0) {
                ALOGE("SELinux: Failed to acquire service_manager context. Aborting.
    ");
                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.c循环,等待客户请求
        binder_loop(bs, svcmgr_handler);
    
        return 0;
    }
    struct binder_state *binder_open(size_t mapsize)
    {
        。。。
      //打开设备节点
        bs->fd = open("/dev/binder", O_RDWR);
        。。。
    //映射 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); 。。。 }

    再看看直接的那个回调函数

    int svcmgr_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        。。。
        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;
         //想servicemanager添加服务 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 ", 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 ", txn->code); return -1; } bio_put_uint32(reply, 0); return 0; }
    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));
    
        for (;;) {
            bwr.read_size = sizeof(readbuf);
            bwr.read_consumed = 0;
            bwr.read_buffer = (uintptr_t) readbuf;
         //读取binder节点数据
            res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
        
            if (res < 0) {
                ALOGE("binder_loop: ioctl failed (%s)
    ", strerror(errno));
                break;
            }
         //解析
            res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
            if (res == 0) {
                ALOGE("binder_loop: unexpected reply?!
    ");
                break;
            }
            if (res < 0) {
                ALOGE("binder_loop: io error %d %s
    ", res, strerror(errno));
                break;
            }
        }
    }
    int binder_parse(struct binder_state *bs, struct binder_io *bio,
                     uintptr_t ptr, size_t size, binder_handler func)
    {
          。。。
           switch(cmd) {
              。。。
                binder_dump_txn(txn);
                if (func) {
                    unsigned rdata[256/4];
                    struct binder_io msg;
                    struct binder_io reply;
                    int res;
    
                    bio_init(&reply, rdata, sizeof(rdata), 4);
                    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; } 。。。default: ALOGE("parse: OOPS %d ", cmd); return -1; } } return r; }

    小结:

    1.申请一段内存,打开设备节点/dev/binder,同时将内存映射到内核中用来给binder使用

    2.将自己设置为服务管理者

    3.通过binder接口循环读取查看是否有数据,当有数据传来时,调用回调函数添加服务,或者查询服务

  • 相关阅读:
    Flink window机制
    用上帝视角来看待组件的设计模式
    npm和package.json那些不为常人所知的小秘密
    四步走查智能硬件异常Case
    PorterDuffXfermode 图像混合技术在漫画APP中的应用
    发布流程进化史
    新手入门Sqlalchemy
    OpenResty 最佳实践 (2)
    更新数据库触发器
    删除约束名字段名
  • 原文地址:https://www.cnblogs.com/maogefff/p/7661289.html
Copyright © 2011-2022 走看看