对于ServiceManager的理解

ServiceManager是什么?

ServiceManager是binder服务的大管家,由Init进程解析init.rc文件创建,其本身也是一个Binder服务,但并没有采用libbinder中的多线程模型来与Binder驱动通信,而是自行编写了binder.c直接和Binder驱动来通信,并且只有一个循环binder_loop来进行读取和处理事务,这样的好处是简单而高效。

ServiceManager的作用?

ServiceManager的作用相对简单,主要是“注册和查询”服务。

ServiceManager的工作流程?

启动流程

Init进程解析配置文件,其所对应的可执行程序/system/bin/servicemanager,所对应的源文件是service_manager.c

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()方法,代码如下:

int main(int argc, char **argv) {
    struct binder_state *bs;
    //打开binder驱动,申请128k字节大小的内存空间 【见小节2.2】
    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端发来的请求 【见小节2.4】
    binder_loop(bs, svcmgr_handler);
    return 0;
}

主要有下面三个流程:

  • 打开binder驱动:binder_open;
  • 注册成为binder服务的大管家:binder_become_context_manager;
  • 进入无限循环,处理client端发来的请求:binder_loop;

添加服务

ServiceManager对应的Java类是ServiceManager.java,Android中的系统服务注册正式通过这个类完成的。我们看看它的addService方法:

  public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

再看看getIServiceManager()方法:

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

可以看到是通过BinderInternal.getContextObject()转换成IServiceManager这个binder代理类的,我们看看它的方法介绍:

    /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     */
    public static final native IBinder getContextObject();

看注释可以知道这个返回的IBinder就是IServiceManager的binder代理类,为什么要这么做呢?因为其他进程和ServiceManager通讯的目的是为了注册或者查询服务,但是这些进程和ServiceManager又是属于不同但进程,这里又需要跨进程通讯,所以Native层就干脆把IServiceManager的binder放在固定的一个位置,其他进程可以直接拿到这个IBinder对象。

原文地址:https://www.cnblogs.com/monsterdev/p/12685105.html