(N)Telephony分析(二)之SystemServer启动

来源:互联网 发布:侧面导航栏网站源码 编辑:程序博客网 时间:2024/05/21 10:24

已经了解了zygote的启动,那么接着zygote启动,往后继续分析

zygote在启动的时候,启动的是一个进程,为/system/bin/app_process,而这个app_process的进程,是在app_main.cpp文件中启动的,查看其main函数

frameworks/base/cmds/app_process/app_main.cpp文件

int main(int argc, char* const argv[]){    ......    // Leo, 定义AppRuntime    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));    ......    // Parse runtime arguments.  Stop at first unrecognized option.    bool zygote = false;    bool startSystemServer = false;    bool application = false;    String8 niceName;    String8 className;    ++i;  // Skip unused "parent dir" argument.    // Leo, 根据在zygote启动的init.zygote32.rc文件中的数据配置参数    while (i < argc) {        const char* arg = argv[i++];        if (strcmp(arg, "--zygote") == 0) {            zygote = true;            niceName = ZYGOTE_NICE_NAME; // zygote        } else if (strcmp(arg, "--start-system-server") == 0) {            startSystemServer = true;        } else if (strcmp(arg, "--application") == 0) {            application = true;        } else if (strncmp(arg, "--nice-name=", 12) == 0) {            niceName.setTo(arg + 12);        } else if (strncmp(arg, "--", 2) != 0) {            className.setTo(arg);            break;        } else {            --i;            break;        }    }    Vector<String8> args;    if (!className.isEmpty()) {        // We're not in zygote mode, the only argument we need to pass        // to RuntimeInit is the application argument.        //        // The Remainder of args get passed to startup class main(). Make        // copies of them before we overwrite them with the process name.        args.add(application ? String8("application") : String8("tool"));        runtime.setClassNameAndArgs(className, argc - i, argv + i);    } else {        ......    }    if (!niceName.isEmpty()) {        runtime.setArgv0(niceName.string());
// Leo,将app_process进程名称改为zygote        set_process_name(niceName.string());    }    if (zygote) {        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);    } else if (className) {        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);    } else {        fprintf(stderr, "Error: no class name or --zygote supplied.\n");        app_usage();        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");        return 10;    }
从app_main.cpp文件的main函数中,我们可以看到,

1. 在刚开始,通过zygote启动时传入的参数

2. 将app_process的进程名称改为zygote进程

3. 配置一下AppRuntime的参数值

4. 由于传入的zygote为true,因此会start ZygoteInit方法

那么看看runtime的start方法

AndroidRuntime.cpp文件

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){    ALOGD(">>>>>> START %s uid %d <<<<<<\n",            className != NULL ? className : "(unknown)", getuid());    static const String8 startSystemServer("start-system-server");    /*     * 'startSystemServer == true' means runtime is obsolete and not run from     * init.rc anymore, so we print out the boot start event here.     */    for (size_t i = 0; i < options.size(); ++i) {        if (options[i] == startSystemServer) {           /* track our progress through the boot sequence */           const int LOG_BOOT_PROGRESS_START = 3000;           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));        }    }    const char* rootDir = getenv("ANDROID_ROOT");    if (rootDir == NULL) {        rootDir = "/system";        if (!hasDir("/system")) {            LOG_FATAL("No root directory specified, and /android does not exist.");            return;        }        setenv("ANDROID_ROOT", rootDir, 1);    }    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);    /* start the virtual machine */    JniInvocation jni_invocation;    jni_invocation.Init(NULL);    JNIEnv* env;    // Leo, 创建虚拟机的一系列配置    if (startVm(&mJavaVM, &env, zygote) != 0) {        return;    }    onVmCreated(env);    /*     * Register android functions.     */    // Leo, 注册JNI    if (startReg(env) < 0) {        ALOGE("Unable to register all android natives\n");        return;    }    /*     * We want to call main() with a String array with arguments in it.     * At present we have two arguments, the class name and an option string.     * Create an array to hold them.     */    jclass stringClass;    jobjectArray strArray;    jstring classNameStr;    stringClass = env->FindClass("java/lang/String");    assert(stringClass != NULL);    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);    assert(strArray != NULL);    // Leo,classname传入的为com.android.internal.os.ZygoteInit    classNameStr = env->NewStringUTF(className);    assert(classNameStr != NULL);    env->SetObjectArrayElement(strArray, 0, classNameStr);    for (size_t i = 0; i < options.size(); ++i) {        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());        assert(optionsStr != NULL);        env->SetObjectArrayElement(strArray, i + 1, optionsStr);    }    /*     * Start VM.  This thread becomes the main thread of the VM, and will     * not return until the VM exits.     */    char* slashClassName = toSlashClassName(className);    jclass startClass = env->FindClass(slashClassName);    if (startClass == NULL) {        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);        /* keep going */    } else {    // Leo,找到main函数        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",            "([Ljava/lang/String;)V");        if (startMeth == NULL) {            ALOGE("JavaVM unable to find main() in '%s'\n", className);            /* keep going */        } else {        // Leo,调用com.android.internal.os.ZygoteInit的main方法            env->CallStaticVoidMethod(startClass, startMeth, strArray);#if 0            if (env->ExceptionCheck())                threadExitUncaughtException(env);#endif        }    }    free(slashClassName);    ALOGD("Shutting down VM\n");    if (mJavaVM->DetachCurrentThread() != JNI_OK)        ALOGW("Warning: unable to detach main thread\n");    if (mJavaVM->DestroyJavaVM() != 0)        ALOGW("Warning: VM did not shut down cleanly\n");}
从AndroidRuntime的start方法中,我们可以知道,在这个方法中,主要是做了

1. startVm,创建虚拟机

2. startReg,注册JNI环境

3. 调用ZygoteInit方法的main函数

前两条,暂不分析,由此,我们进入了JAVA世界

ZygoteInit.java文件

public static void main(String argv[]) {    ......    try {        ......        boolean startSystemServer = false;        String socketName = "zygote";        String abiList = null;        for (int i = 1; i < argv.length; i++) {            if ("start-system-server".equals(argv[i])) {            // Leo,从zygote处传入的参数,此地为true                startSystemServer = true;            } else if (argv[i].startsWith(ABI_LIST_ARG)) {                abiList = argv[i].substring(ABI_LIST_ARG.length());            } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {                socketName = argv[i].substring(SOCKET_NAME_ARG.length());            } else {                throw new RuntimeException("Unknown command line argument: " + argv[i]);            }        }        ......        // Leo, 注册zygote的socket        registerZygoteSocket(socketName);        ......        // Leo,加载一些class/resources等        preload();        ......        // Leo,开启SystemServer世界        if (startSystemServer) {            startSystemServer(abiList, socketName);        }        ......        // Leo,        runSelectLoop(abiList);        closeServerSocket();    } catch (MethodAndArgsCaller caller) {        caller.run();    } catch (Throwable ex) {        Log.e(TAG, "Zygote died with exception", ex);        closeServerSocket();        throw ex;    }}
从这部分代码中可以看到,调用startSystemServer来启动SystemServer

private static boolean startSystemServer(String abiList, String socketName)        throws MethodAndArgsCaller, RuntimeException {    ......    /* Hardcoded command line to start the system server */    // Leo,SystemServer的各个参数    String args[] = {        "--setuid=1000",        "--setgid=1000",        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",        "--capabilities=" + capabilities + "," + capabilities,        "--nice-name=system_server",        "--runtime-args",        "com.android.server.SystemServer",    };    ZygoteConnection.Arguments parsedArgs = null;    int pid;    try {    // Leo,写入各个参数        parsedArgs = new ZygoteConnection.Arguments(args);        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);        /* Request to fork the system server process */        // Leo,fork一个进程,这个进程应该就是SystemServer吧        pid = Zygote.forkSystemServer(                parsedArgs.uid, parsedArgs.gid,                parsedArgs.gids,                parsedArgs.debugFlags,                null,                parsedArgs.permittedCapabilities,                parsedArgs.effectiveCapabilities);    } catch (IllegalArgumentException ex) {        throw new RuntimeException(ex);    }    /* For child process */    if (pid == 0) {        ......        // Leo, SystemServer的具体作用        handleSystemServerProcess(parsedArgs);    }    return true;}
从这边可以看到,设置SystemServer的一些参数,然后通过Zygote的forkSystemServer方法,创建一个nice_name为system_server的进程,自此,SystemServer就被创建了,那么SystemServer进程的具体作用是什么呢

private static void handleSystemServerProcess(        ZygoteConnection.Arguments parsedArgs)        throws ZygoteInit.MethodAndArgsCaller {// Leo, 关闭与zygote的Socket通信    closeServerSocket();    // set umask to 0077 so new files and directories will default to owner-only permissions.    Os.umask(S_IRWXG | S_IRWXO);    if (parsedArgs.niceName != null) {        Process.setArgV0(parsedArgs.niceName);    }    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");    if (systemServerClasspath != null) {        performSystemServerDexOpt(systemServerClasspath);    }    if (parsedArgs.invokeWith != null) {        String[] args = parsedArgs.remainingArgs;        // If we have a non-null system server class path, we'll have to duplicate the        // existing arguments and append the classpath to it. ART will handle the classpath        // correctly when we exec a new process.        if (systemServerClasspath != null) {            String[] amendedArgs = new String[args.length + 2];            amendedArgs[0] = "-cp";            amendedArgs[1] = systemServerClasspath;            System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);        }        WrapperInit.execApplication(parsedArgs.invokeWith,                parsedArgs.niceName, parsedArgs.targetSdkVersion,                VMRuntime.getCurrentInstructionSet(), null, args);    } else {        ClassLoader cl = null;        if (systemServerClasspath != null) {            cl = createSystemServerClassLoader(systemServerClasspath,                                               parsedArgs.targetSdkVersion);            Thread.currentThread().setContextClassLoader(cl);        }        /*         * Pass the remaining arguments to SystemServer.         */        // Leo,调用RuntimeInit的zygoteInit方法        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);    }    /* should never reach here */}
此处先关闭与zygote的socket通信,独立完成自己的任务,然后调用了RuntimeInit的zygoteInit方法

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");        redirectLogStreams();        // Leo,做一些常规的初始化操作        commonInit();        // Leo,初始化native层        nativeZygoteInit();        // Leo, 初始化一些应用?我们分析看看~        applicationInit(targetSdkVersion, argv, classLoader);    }
在这个方法中,可以看到做了一些初始化操作,我们直接看最后一个方法

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)        throws ZygoteInit.MethodAndArgsCaller {    ......    // Remaining arguments are passed to the start class's static main    invokeStaticMain(args.startClass, args.startArgs, classLoader);}
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        Class<?> cl;        try {        // Leo, classname为com.android.server.SystemServer            cl = Class.forName(className, true, classLoader);        } catch (ClassNotFoundException ex) {            throw new RuntimeException(                    "Missing class when invoking static main " + className,                    ex);        }        Method m;        try {            m = cl.getMethod("main", new Class[] { String[].class });        } catch (NoSuchMethodException ex) {            throw new RuntimeException(                    "Missing static main on " + className, ex);        } catch (SecurityException ex) {            throw new RuntimeException(                    "Problem getting static main on " + className, ex);        }        int modifiers = m.getModifiers();        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {            throw new RuntimeException(                    "Main method is not public and static on " + className);        }        /*         * This throw gets caught in ZygoteInit.main(), which responds         * by invoking the exception's run() method. This arrangement         * clears up all the stack frames that were required in setting         * up the process.         */        throw new ZygoteInit.MethodAndArgsCaller(m, argv);    }
从这个方法中可以看到,取出SystemServer的main方法,然后抛出ZygoteInit.MethidAndArgsCaller异常,那么在哪儿catch这个异常的呢?追溯到前面,可以看到,在ZygoteInit的main函数中,有catch这个异常,并且直接调用了这个caller的run方法,因此,进入MethodAndArgsCaller的run方法

public static class MethodAndArgsCaller extends Exception        implements Runnable {    /** method to call */    private final Method mMethod;    /** argument array */    private final String[] mArgs;    public MethodAndArgsCaller(Method method, String[] args) {        mMethod = method;        mArgs = args;    }    public void run() {        try {            mMethod.invoke(null, new Object[] { mArgs });        } catch (IllegalAccessException ex) {            throw new RuntimeException(ex);        } catch (InvocationTargetException ex) {            Throwable cause = ex.getCause();            if (cause instanceof RuntimeException) {                throw (RuntimeException) cause;            } else if (cause instanceof Error) {                throw (Error) cause;            }            throw new RuntimeException(ex);        }    }}
反射机制,直接调用了SystemServer的main方法,自此,进入了SystemServer的java世界
阅读全文
0 0