Android 8.0 启动ServiceManager

来源:互联网 发布:微屏软件 编辑:程序博客网 时间:2024/05/18 22:17

一、简述

framework/native/cmds/servicemanager/  - service_manager.c  - binder.c  kernel/drivers/ (不同Linux分支路径略有不同)  - staging/android/binder.c  - android/binder.c 

ServiceManager是Binder IPC通信过程中的守护进程,本身也是一个Binder服务,但并没有采用libbinder中的多线程模型来与Binder驱动通信,而是自行编写了binder.c直接和Binder驱动来通信,并且只有一个循环binder_loop来进行读取和处理事务,这样的好处是简单而高效。

ServiceManager本身工作相对简单,其功能:查询和注册服务。 对于Binder IPC通信过程中,其实更多的情形是BpBinder和BBinder之间的通信,比如ActivityManagerProxy和ActivityManagerService之间的通信等。


流程

启动过程

ServiceManager是由init进程通过解析init.rc文件而创建的,其所对应的可执行程序/system/bin/servicemanager,所对应的源文件是service_manager.c,进程名为/system/bin/servicemanager。

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

启动Service Manager的入口函数是service_manager.c中的main()方法,代码如下:

main

[ -> service_manager.c]

int main(int argc, char **argv){    struct binder_state *bs;    //打开binder驱动,申请128k字节大小的内存空间    bs = binder_open(128*1024);    ...    //成为上下文管理者 【见小节2.3】    if (binder_become_context_manager(bs)) {        return -1;    }    selinux_enabled = is_selinux_enabled(); //selinux权限是否使能    sehandle = selinux_android_service_context_handle();    selinux_status_open(true);    if (selinux_enabled > 0) {        if (sehandle == NULL) {              abort(); //无法获取sehandle        }        if (getcon(&service_manager_context) != 0) {            abort(); //无法获取service_manager上下文        }    }    ...    //进入无限循环,处理client端发来的请求    binder_loop(bs, svcmgr_handler);    return 0;}

二、核心工作

servicemanager的核心工作就是注册服务和查询服务

2.1 do_find_service

[-> service_manager.c]

uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid){    //查询相应的服务    struct svcinfo *si = find_svc(s, len);    if (!si || !si->handle) {        return 0;    }    if (!si->allow_isolated) {        uid_t appid = uid % AID_USER;        //检查该服务是否允许孤立于进程而单独存在        if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {            return 0;        }    }    //服务是否满足查询条件    if (!svc_can_find(s, len, spid)) {        return 0;    }    return si->handle;}

查询到目标服务,并返回该服务所对应的handle

2.1.1 find_svc

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;}

从svclist服务列表中,根据服务名遍历查找是否已经注册。当服务已存在svclist,则返回相应的服务名,否则返回NULL。

当找到服务的handle, 则调用bio_put_ref(reply, handle),将handle封装到reply.

2.2 do_add_service

[-> service_manager.c]

int do_add_service(struct binder_state *bs,                   const uint16_t *s, size_t len,                   uint32_t handle, uid_t uid, int allow_isolated,                   pid_t spid){    struct svcinfo *si;    if (!handle || (len == 0) || (len > 127))        return -1;    //权限检查,>=AID_APP    if (!svc_can_register(s, len, spid)) {        return -1;    }    //服务检索    si = find_svc(s, len);    if (si) {        if (si->handle) {            svcinfo_death(bs, si); //服务已注册时,释放相应的服务        }        si->handle = handle;    } else {        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));        if (!si) {  //内存不足,无法分配足够内存            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->next = svclist; // svclist保存所有已注册的服务        svclist = si;    }    //以BC_ACQUIRE命令,handle为目标的信息,通过ioctl发送给binder驱动    binder_acquire(bs, handle);    //以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通过ioctl发送给binder驱动,主要用于清理内存等收尾工作    binder_link_to_death(bs, handle, &si->death);    return 0;}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, perm, str8(name, name_len)) ? 1 : 0;} 

注册服务的分以下3部分工作:

  • svc_can_register:检查权限,检查selinux权限是否满足;
  • find_svc:服务检索,根据服务名来查询匹配的服务;
  • svcinfo_death:释放服务,当查询到已存在同名的服务,则先清理该服务信息,再将当前的服务加入到服务列表svclist;

三. 总结

ServiceManger集中管理系统内的所有服务,通过权限控制进程是否有权注册服务,通过字符串名称来查找对应的Service;由于ServiceManger进程建立跟所有向其注册服务的死亡通知, 那么当服务所在进程死亡后, 会只需告知ServiceManager.每个Client通过查询ServiceManager可获取Server进程的情况,降低所有Client进程直接检测会导致负载过重。

ServiceManager启动流程:

  1. 打开binder驱动,并调用mmap()方法分配128k的内存映射空间:binder_open();
  2. 通知binder驱动使其成为守护进程:binder_become_context_manager();
  3. 验证selinux权限,判断进程是否有权注册或查看指定服务;
  4. 进入循环状态,等待Client端的请求:binder_loop()。
  5. 注册服务的过程,根据服务名称,但同一个服务已注册,重新注册前会先移除之前的注册信息;
  6. 死亡通知: 当binder所在进程死亡后,会调用binder_release方法,然后调用binder_node_release.这个过程便会发出死亡通知的回调.

ServiceManager最核心的两个功能为查询和注册服务:

  • 注册服务:记录服务名和handle信息,保存到svclist列表;
  • 查询服务:根据服务名查询相应的的handle信息。

四. 源码目录

从上之下, 整个Binder架构所涉及的总共有以下5个目录:

/framework/base/core/java/               (Java)/framework/base/core/jni/                (JNI)/framework/native/libs/binder            (Native)/framework/native/cmds/servicemanager/   (Native)/kernel/drivers/staging/android          (Driver)

4.1 Java framework

/framework/base/core/java/android/os/      - IInterface.java    - IBinder.java    - Parcel.java    - IServiceManager.java    - ServiceManager.java    - ServiceManagerNative.java    - Binder.java  /framework/base/core/jni/        - android_os_Parcel.cpp    - AndroidRuntime.cpp    - android_util_Binder.cpp (核心类)

4.2 Native framework

/framework/native/libs/binder             - IServiceManager.cpp    - BpBinder.cpp    - Binder.cpp    - IPCThreadState.cpp (核心类)    - ProcessState.cpp  (核心类)/framework/native/include/binder/    - IServiceManager.h    - IInterface.h/framework/native/cmds/servicemanager/    - service_manager.c    - binder.c

4.3 Kernel

/kernel/drivers/staging/android/    - binder.c    - uapi/binder.h


参考网址:

http://gityuan.com/2015/11/07/binder-start-sm/

原创粉丝点击