【Binder 机制】Native 层 Binder 机制分析 ( 注册 Binder 服务 | svcmgr_handler | do_add_service | find_svc )

简介: 【Binder 机制】Native 层 Binder 机制分析 ( 注册 Binder 服务 | svcmgr_handler | do_add_service | find_svc )

文章目录

前言

一、注册 Binder 服务

二、service_manager.c | do_add_service

三、service_manager.c | svc_can_register

四、service_manager.c | find_svc

五、service_manager.c | svcinfo_death

前言

在上一篇博客 【Binder 机制】Native 层 Binder 机制分析 ( binder_loop | svcmgr_handler | binder.c | binder_parse ) 中 , 简单介绍了 在 service_manager.c 中的 main 函数中调用了 binder_loop 方法 , 在 binder_loop 方法中 , 传入了 svcmgr_handler 方法作为回调函数 , svcmgr_handler 中可以接收不同的消息 , 处理不同的业务 ;






一、注册 Binder 服务


参考 【Binder 机制】Native 层 Binder 机制分析 ( binder_loop | svcmgr_handler | binder.c | binder_parse ) 二、binder_loop 方法参数 svcmgr_handler 章节 ;


在 svcmgr_handler 方法中 , 添加服务 , 需要执行如下逻辑 : 接收到 SVC_MGR_ADD_SERVICE 消息 , 添加 Binder 服务 , 主要调用 do_add_service 方法 ;


i

nt svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
  // 链表 
    struct svcinfo *si;
  // 根据不同的 txn->code 执行不同的方法 
    switch(txn->code) {
    case SVC_MGR_ADD_SERVICE:// 收到消息 , 添加一个 Binder 服务
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        dumpsys_priority = bio_get_uint32(msg);
        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
                           txn->sender_pid))
            return -1;
        break;
    }
    return 0;
}


完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c






二、service_manager.c | do_add_service


do_add_service 中进行如下操作 :


首先 , 进行权限检测 , 检测是否有权限注册 Service , 调用 svc_can_register 方法实现 ;


然后 , 调用 find_svc 方法 , 查找 Service ;


查找到服务 , 服务不为空 , 说明之前注册过该服务 , 则先释放服务 ;

查找到服务为空 , 则为服务分配内存空间 , 创建服务 , 并挂载到 svclist 列表中 ;

int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
    struct svcinfo *si;
    if (!handle || (len == 0) || (len > 127))
        return -1;
  // 权限检测 : 检测是否有权限注册 Service 
    if (!svc_can_register(s, len, spid, uid)) {
        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
             str8(s, len), handle, uid);
        // 权限检测失败直接返回 
        return -1;
    }// 权限检测通过 
  // 查找 Service 
    si = find_svc(s, len);
    if (si) { // 查找到服务 , 服务不为空 
        if (si->handle) {
            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
                 str8(s, len), handle, uid);
    // 服务不为空时的处理 
    // 如果之前注册过该服务 , 则先释放服务 
            svcinfo_death(bs, si);
        }
        si->handle = handle;
    } else { // 没有查找到服务 , 服务为空 
  // 为服务分配内存空间 
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {
          // 内存不足 , 注册失败 
            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
                 str8(s, len), handle, uid);
            return -1;
        }
        si->handle = handle;
        si->len = len;
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = '\0';
        si->death.func = (void*) svcinfo_death;
        si->death.ptr = si;
        si->allow_isolated = allow_isolated;
        si->dumpsys_priority = dumpsys_priority;
        // 设置成功后 , 将分配的 si 挂载到 svclist 链表中 
        si->next = svclist;
        svclist = si;
    }
    binder_acquire(bs, handle);
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}


完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c






三、service_manager.c | svc_can_register


权限检测 , 是否可以注册服务 ;


static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
{
    const char *perm = "add";
    if (multiuser_get_app_id(uid) >= AID_APP) {
        return 0; /* Don't allow apps to register services */
    }
    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
}


完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c






四、service_manager.c | find_svc


find_svc 查找服务方法 , 从 svclist 链表中寻找匹配 Service ; 所有的服务都存在该链表中 ;


struct svcinfo *svclist = NULL;
struct svcinfo *find_svc(const uint16_t *s16, size_t len)
{
    struct svcinfo *si;
    for (si = svclist; si; si = si->next) {
      // 先匹配长度是否一样
        if ((len == si->len) &&
          // 然后匹配名字是否一样
            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
            // 如果查找到对应服务 , 返回该服务 
            return si;
        }
    }
    // 如果没有找到服务 , 则返回空 
    return NULL;
}


完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c






五、service_manager.c | svcinfo_death


查找服务 , 服务不为空时 , 调用 svcinfo_death 方法 , 该方法中调用 binder_release 方法释放 Binder ;


void svcinfo_death(struct binder_state *bs, void *ptr)
{
    struct svcinfo *si = (struct svcinfo* ) ptr;
    ALOGI("service '%s' died\n", str8(si->name, si->len));
    if (si->handle) {
      // 如果之前注册过 Binder , 先释放 Binder 
        binder_release(bs, si->handle);
        si->handle = 0;
    }
}


完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c


目录
相关文章
|
存储 Java Android开发
听说你Binder机制学的不错,来面试下这几个问题(二)
听说你Binder机制学的不错,来面试下这几个问题(二)
238 0
听说你Binder机制学的不错,来面试下这几个问题(二)
|
存储 缓存 Java
听说你Binder机制学的不错,来面试下这几个问题(三)
听说你Binder机制学的不错,来面试下这几个问题(三)
234 0
听说你Binder机制学的不错,来面试下这几个问题(三)
|
存储 Java 大数据
听说你Binder机制学的不错,来面试下这几个问题(一)
听说你Binder机制学的不错,来面试下这几个问题(一)
625 0
听说你Binder机制学的不错,来面试下这几个问题(一)
|
Java Android开发
Binder机制中的收发消息及线程池
在阅读《深入理解android内核设计思想》的有关Binder章节的时候,发现书中有部分问题没有很清晰的描述清楚,所以这篇文章主要是针对收发消息的过程和线程池这两个知识点详细展开一下。注意本篇文章并不是介绍Binder机制,而是针对它的两个小细节深入探讨一下,所以建议大家先详细的阅读《深入理解android内核设计思想》中有关Binder章节后对照阅读本篇文章。
313 0
|
消息中间件 存储 缓存
Android进程间通信之一:Binder机制学习
Android进程间通信之一:Binder机制学习
177 0
Android进程间通信之一:Binder机制学习
|
Java Android开发 C++
【Binder 机制】Native 层 Binder 机制分析 ( 查找 Binder 服务 | svcmgr_handler | do_find_service )
【Binder 机制】Native 层 Binder 机制分析 ( 查找 Binder 服务 | svcmgr_handler | do_find_service )
114 0
|
Java Android开发 C++
Android中的Binder概述
Android应用的开发离不开四大组件(Activity,Service,BroadcastReceiver,ContentProvider),而这四大组件所涉及的通信底层都是依赖于Binder IPC机制的。例如当进程A中的Activity要向进程B中的Service通信,这便需要依赖于Binder IPC。不仅如此,整个Android系统架构中,大量采用了Binder机制作为IPC方案,当然也存在部分其它的IPC方式,比如Zygote通信便是采用Socket。 概念:Binder是Android中的一种IPC方式,提供远程过程调用(RFC)功能。
|
Java 开发工具 Android开发
Android中的Binder学习笔记
Android中的Binder学习笔记
Android中的Binder学习笔记
|
Android开发
Android后台杀死系列之四:Binder讣告原理
Android后台杀死系列之四:Binder讣告原理
324 0
Android后台杀死系列之四:Binder讣告原理