关闭

结合源码探讨Android系统的启动流程

292人阅读 评论(0) 收藏 举报
分类:

本文的分析是基于Android 5.0.0 Google原生代码的。

由于本人能力有限,所考虑或者疏忽错漏的地方或多或少应该存在。同时,Android从启动过程开始,实际上就涉及多个技术难点和多种通信机制的知识点。

基于上面两个原因,笔者会一直修改,补充,拓展此文。希望能够坚持下去,从而真正达到触类旁通。


从我们长按手机电源键,到安卓系统完全启动之间,总共经历了以下五个阶段。

第一步:启动电源以及系统启动

当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。

第二步:引导程序

引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。

 引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。

第三步:内核的启动

Android内核与桌面Linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动init进程。

第四步:init进程的启动

init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程将进行两个主要操作,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。

 

其实第一步到第三步,可以理解为是一个Linux内核的启动的过程。从第四步开始,Android系统才可以算作是“真正”的开始启动。这也是本文所关注的重点起始的地方。先从init.rc脚本开始讲起。

.rc文件是安卓初始化语言,有特定的格式以及规则。例如:

service <name><pathname> [<argument>]*

    <option>

    <option>

...

 如上所示,这个语法代表的是启动一个指定路径的服务。

在init.rc这个配置文件中,涉及到两个最关键的步骤:

(init.rc文件既可在源码目录/system/core/rootdir,也可在设备根目录下找到)

1.启动ServiceManager进程

service servicemanager /system/bin/servicemanager

ServiceManager是Binder的服务管理守护进程,是Binder的核心,由其使用Binder驱动进行IPC管理,关于IPC通讯 的机制,此处暂不详述。在APP和Framework中,应用程序使用的ServiceManager.java就是通过Proxy与这个守护进程进行的 通讯。

2. 启动Zygote进程,Zygote的中文翻译是受精卵或孵化器,顾名思义,从它开始将会衍生出Android系统中的各种子进程。

service zygote /system/bin/app_process -Xzygote/system/bin --zygote --start-system-server

第五阶段:Zygote进程加载SystemServer进程,并启动系统服务

如果在init.rc文件中找不到这一语句,我们可以关注下init.rc文件开头的几行import代码。

 import/init.environ.rc
 import /init.usb.rc
 import /init.${ro.hardware}.rc
 import /init.${ro.zygote}.rc  //在同一目录下,可以找到类似于init.zygote32.rc的文件
                               //不同名字的zygote进程启动文件对应于不同位数的设备
 import /init.trace.rc

随便打开一个init.zygote32.rc文件,即可找到此语句

在这个步骤中,将启动zygote服务进程。Zygote进程将成为所有应用进程的孵化器。

我们来看一下app_process的代码,位置是在:

frameworks/base/cmds/app_process/app_main.cpp

C++文件的执行入口总在main()函数当中——其入口函数main在文件app_main.cpp中,接下来我们就从这个main函数入手来分析zygote的内部逻辑。

/*启动zygote的方式为service zygote /system/bin/app_process-Xzygote /system/bin --zygote --start-system-server

* 所以 argc == 5, argv中存的就是这5个参数argv[0]=="/system/bin/app_process" ,argv[1]== "-Xzygote"....

*/

int main(int argc, char* const argv[])
{
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
        // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
        // EINVAL. Don't die on such kernels.
        if (errno != EINVAL) {
            LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
            return 12;
        }
    }

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.

    int i;
    for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }
        runtime.addOption(strdup(argv[i]));
    }

    // 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.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) { //将会走这个分支
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } 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) { //启动zygote中的参数都不会走到这个分支,仔细思考下就知道是因为所有带"--"的参数都会先被前面的if判断分支截获
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    //经历了上面的while循环后,总结下变量的赋值和变化情况:
    //boolean zygote 变为true
    //boolean startSystemServer变为true
    //boolean application依然为false
    //字符串变量niceName和className为Null 
    //在这个基础上分析下面的流程就很容易了
    Vector<String8> args;  //重点关注下这个变量,它将作为接下来调用runtime.start()方法的传入参数
    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 {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server")); //args中添加的第一个变量
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag); //args中添加的第二个变量

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

    if (zygote) { 
        runtime.start("com.android.internal.os.ZygoteInit", args); //zygote为true
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args);
    } 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_process/app_main.cpp这个文件的最后,将会调用runtime.start("com.android.internal.os.ZygoteInit",args); 这个语句runtime是一个AppRuntime变量,其定义同样在/frameworks/base/cmds/app_process/app_main.cpp这个文件当中。  
 class AppRuntime : public AndroidRuntime 
{ 

        ...... 

};  

可以发现其继承于AndroidRuntime类。AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中。

runtime.start方法调用的正是其父类AndroidRuntime.cpp中的start方法。

 AndroidRuntime.start()方法代码如下:

/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
    ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
            className != NULL ? className : "(unknown)");

    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;
    if (startVm(&mJavaVM, &env) != 0) {   //关键步骤1,开启虚拟机
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions. //关键步骤2,注册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);
    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. //关键步骤3
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        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 {
            env->CallStaticVoidMethod(startClass, startMeth, strArray); //调用其main方法

#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");
}
这个方法,除去一些系统启动过程中的出错处理和相关信息排查操作,总体逻辑还是比较清晰的。关注几个关键的步骤可以知道,这个方法完成了三个最重要的责任:

关键步骤1——调用函数startVM,启动虚拟机

关键步骤2——调用函数startReg注册JNI方法,以完成安卓上层和native层的交互

关键步骤3——找到className为” com.android.internal.os.ZygoteInit”的类,并调用其main方法


接着前行,步骤3中涉及到这个类定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中。找到其函数入口main方法:

public static void main(String argv[]) {
        try {
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    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]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            registerZygoteSocket(socketName); //关键步骤1,注册Zygote进程的套接字
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());

            // Finish profiling the zygote initialization.
            SamplingProfilerIntegration.writeZygoteSnapshot();

            // Do an initial gc to clean up after startup
            gc();

            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false);

            if (startSystemServer) {
                startSystemServer(abiList, socketName);//关键步骤2,启动SystemServer
            }

            Log.i(TAG, "Accepting command socket connections");
            runSelectLoop(abiList);//关键步骤3

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

详细分析这四个关键步骤。

关键步骤1:——调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯

ZygoteInit.registerZygoteSocket():
   /**
     * Registers a server socket for zygote command connections
     *
     * @throws RuntimeException when open fails
     */
    private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; //安卓规范套接字前缀+socket名字
            try {
                String env = System.getenv(fullSocketName);
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                sServerSocket = new LocalServerSocket(
                        createFileDescriptor(fileDesc));//创建一个文件描述符
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    } 

关键步骤2:——调用startSystemServer,启动SystemServer这个系统核心进程

startSystemServer方法位于同一文件ZygoteInit.java当中。

ZygoteInit.startSystemServer():

    /**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_BLOCK_SUSPEND,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer( //与Android 4.4之前的版本不一样的地方
                    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) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

这里我们可以看到,Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer组件,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。

ZygoteInit.handleSystemServerProcess():
    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        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,
                    null, args);
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

这个函数接着调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操作。

RuntimeInit.zygoteInit函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中。

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

        redirectLogStreams();

        commonInit();
        nativeZygoteInit(); //调用了JNI层的方法,为Binder通信机制的建立奠定了基础,此处暂不深入讨论

        applicationInit(targetSdkVersion, argv, classLoader);
    }

继续查看RuntimeInit.applicationInit()方法
    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        final Arguments args;
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        }
        
        // Remaining arguments are passed to the start class's static main
        /*
        *从ZygoteInit.startSystemServer()方法中传过来的parsedArgs参数包括 
        *"--nice-name=system_server", "com.android.server.SystemServer"
        *实际上它们就是互相对应的硬编码,调用SystemServer的main方法
        */
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }
    }

不要放弃,继续往下看,到这里我们将调用RuntimeInit.java中的invokeStaticMain方法:

   /**
     * Invokes a static "main(argv[]) method on class "className".
     * Converts various failing exceptions into RuntimeExceptions, with
     * the assumption that they will then cause the VM instance to exit.
     *
     * @param className Fully-qualified class name
     * @param argv Argument vector for main()
     * @param classLoader the classLoader to load {@className} with
     */
    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;

        try {          
            cl = Class.forName(className, true, classLoader);//加载com.android.server.SystemServer这个类
        } 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 });//获取main方法
        } 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);
    }

我们出奇的发现RuntimeInit.invokeStaticMain方法并没有直接调用SystemServer的main的方法,那么它是怎么被调用的?答案在这个函数的末尾——抛出了一个MethodAndArgsCaller异常。源码中注释非常清楚地说明了,这个异常将在main方法中被截获。

public static void main(String argv[]) {
        try {
         ........ //省略掉中间的内容
        } catch (MethodAndArgsCaller caller) {//就是在这里截获的!
            caller.run();
        } catch(RuntimeException ex) {
            Log.e(TAG, "Zygote died withexception", ex);
            closeServerSocket();
            throw ex;
        }
}

目光转移到MethodAndArgsCaller的run()方法。该方法定义在/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java方法中。

 

 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 {
                //在线程的run()方法中开始正式调用main方法
                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方法了。

Android5.0.0以上版本的SystemServer.java文件位于

/frameworks/base/services/java/com/android/server/中

    public static void main(String[] args) {
        new SystemServer().run();
    }
main方法中只有仅仅一句代码。调用了SystemServer的构造函数,并让他以“线程的方式”跑起来。

    public SystemServer() {
        // Checkfor factory test mode.
       mFactoryTestMode = FactoryTest.getMode();
    }

 

    private void run() {
        // If a device's clock is before 1970 (before 0), a lot of
        // APIs crash dealing with negative numbers, notably
        // java.io.File#setLastModified, so instead we fake it and
        // hope that time from cell towers or NTP fixes it shortly.
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        // Here we go!
        Slog.i(TAG, "Entered the Android system server!");
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());

        // In case the runtime switched since last boot (such as when
        // the old runtime was removed in an OTA), set the system
        // property so that it is in sync. We can't do this in
        // libnativehelper's JniInvocation::Init code where we already
        // had to fallback to a different runtime because it is
        // running as root and we need to be the system user to set
        // the property. http://b/11463182
        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

        // Enable the sampling profiler.
        if (SamplingProfilerIntegration.isEnabled()) {
            SamplingProfilerIntegration.start();
            mProfilerSnapshotTimer = new Timer();
            mProfilerSnapshotTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
                }
            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }

        // Mmmmmm... more memory!
        VMRuntime.getRuntime().clearGrowthLimit();

        // The system server has to run all of the time, so it needs to be
        // as efficient as possible with its memory usage.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

        // Some devices rely on runtime fingerprint generation, so make sure
        // we've defined it before booting further.
        Build.ensureFingerprintProperty();

        // Within the system server, it is an error to access Environment paths without
        // explicitly specifying a user.
        Environment.setUserRequired(true);

        // Ensure binder calls into the system always run at foreground priority.
        BinderInternal.disableBackgroundScheduling(true);

        // Prepare the main looper thread (this thread).
        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();

        // Initialize native services.
        //关键步骤1
        System.loadLibrary("android_servers");
        nativeInit();

        // Check whether we failed to shut down last time we tried.
        // This call may not return.
        performPendingShutdown();

        // Initialize the system context.
        createSystemContext();

        //关键步骤2
        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

        //关键步骤3
        // Start services.
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

        // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) {
            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
        }

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

 

SystemServer.run()方法中最值得关注的就是我注释中标注的三个关键步骤,下面稍作解释:

关键步骤1——初始化native层的系统服务。从nativeInit名字就可以看出来这是一个native层的代码,调用了jni层的代码。这个方法的实际实现在:frameworks/base/services/core/jni/com_android_server_SystemServer.cpp。相关代码如下:

</pre><pre name="code" class="cpp">static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }
}

大概就是根据属性配置文件来确定是否需要初始化SensorService,这里就不多介绍了。

关键步骤2——将SystemManagerService注册到SystemServer(自身)中。

关键步骤3——启动系统运行所需的服务。其中:

startBootstrapServices()方法启动ActivityManagerService(AMS),PowerManagerService,PackageManagerServices(),DisplayManagerService等系统关键服务。

startCoreServices()方法调用了一些核心服务,例如LightService,BatteryService等。

startOtherServices()方法则调用剩余的一些服务。出人意料的是,WindowMangaerService竟然是在这里启动。除此之外,还有InputManagerService和AlarmManagerService都在这里启动。

完成了这三个关键步骤后,最后会通过Looper.loop()来进行消息循环,然后处理消息。

此前安卓版本与5.0之后版本SystemServer的启动方式有很大区别:

此前的SystemServer会通过  ServerThread thr = new ServerThread();直接建立一个ServerThread进程。 

 

到这里,系统的关键服务都启动完毕,安卓系统的启动过程也接近尾声。

这里执行完成后,层层返回,最后回到上面的ZygoteInit.main函数中,接下来它就要调用runSelectLoop函数进入一个无限循环在前面ZygoteInit.main函数关键步骤1中创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程了。runSelectLoop()函数实际上是在一死循环中利用zygoteConnection类通过socket的方式进行消息 处理,用于fork出新的zygote,从而以最轻量级的方式实现每个进程一个虚拟机的机制。

 

最后我们再简单梳理下Android启动的过程。毕竟这么复杂的过程需要不断回顾。后续可能会补充上更多流程图,以帮助自己和大家进行梳理。


 

1. Linux内核启动完毕后,系统开始init.rc配置文件启动Zygote进程。

2. Zygote进程的启动经历了ZygoteInit,RuntimeInit,fork出SystemServer这个进程。

3. SystemServer进程负责启动,初始化系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。除了注册到ServiceManager中,还将调用各服务的systemReady()告诉它们系统已经正常启动

4. (老罗总结)当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。


文末感谢下为我提供过帮助的博客大牛和文章,传送门:

1.《Android启动过程深入解析》我所归纳的安卓启动分为几个阶段由此文借鉴。

2.《Android系统进程Zygote启动过程的源代码分析》 安卓名人老罗的传世名作。

3. 《Android情景分析之深入解析system_server》为我解决了不少疑惑。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:12339次
    • 积分:298
    • 等级:
    • 排名:千里之外
    • 原创:16篇
    • 转载:11篇
    • 译文:0篇
    • 评论:3条
    最新评论