Android系统开机启动流程

开机启动步骤


Android 系统启动流程
第一、启动电源
第二、引导程序:Bootloader
第三、Linux 内核启动
第四、init 进程
第五、Zygote 进程的创建
第六、SystemServer 进程的创建
第七、系统启动完成


稍微详细一点的步骤:

1. android 系统初始化

2. BootLoader 进程 (系统启动之后启动此进程)

3. Linux Kernel (内核启动)

4. init.cpp 进程启动 (用户空间第一个进程), PID(进程号)为“1”

init 进程做了三件重要的事:
① 创建(mkdir)和挂载(mount)启动所需的文件目录。其中挂载了 tmpfs、devpts、proc、sysfs 和 selinuxfs 共 5 种文件系统
② 初始化和启动属性服务(property service)
③ 解析 init.rc 配置文件并启动 Zygote 进程 (读取文件配置信息来启动系统相关的各种服务,比如:AMS、WMS、PMS 等等)
其中还有init.zygote32.rc,init.zygote32_64.rc,init.zygote64.rc,init.zygote64_32.rc 这四个文件
其中init.rc 文件中有一句代码: start zygote
Zygote server执行路径为 system/bin/app_process64,对应的文件为 app_main.cpp,这样就会进入 app_main.cpp 的 main 函数,也就是在 Zygote 的 main 函数中,代码如下:
app_main.cpp

// Parse runtime arguments.  Stop at first unrecognized option.
bool zygote = false;
int main(int argc, char* const argv[])
{
...
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) { // 1
            // 如果当前运行在Zygote进程中,则将zygote设置为true
            zygote = true; 
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) { 
            // 如果当前运行在system_server进程中,则将startSystemServer设置为true
            startSystemServer = true; 
        } 
        ...
    }
...
    // 如果运行在zygote进程中
    if (zygote) {
       // 启动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;
    }
...
}

5. 启动 Zygote(孵化器) 进程 可以提前加载一些资源,这样 fork 出的子进程就可以直接使用这些资源,而不用重新加载。比如:system_server 进程就可以直接使用 Zygote 进程中的 JNI 函数、共享库、常用类以及主题资源。

Zygote 进程启动工作了4件事:
① 调用 AppRuntime.cpp 里的AndroidRuntime.start 方法,创建 Java 虚拟机并为其注册 JNI 方法
AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    /* start the virtual machine */
    // 创建JAVA虚拟机(JVM)
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    // 注册android 常用的JNI
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
...
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    // 通过反射调用,比如className为:"com.android.internal.os.ZygoteInit"
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
      // className已设定,那么这里就是找到ZygoteInit 里面的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 {
            // 通过JNI调用ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);
...
}

② 通过 JNI 调用 ZygoteInit.main 方法,从 Native 层进入 Java 框架层
③ 启动 system_server 进程;
④ 通过 ZygoteServer 创建服务器端的 Socket,并通过 ZygoteServer.runSelectLoop 方法等待 AMS 的请求来创建新的应用程序进程;

// com.android.internal.os.ZygoteInit.java 
 public static void main(String argv[]) {
        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();

        try {
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
            RuntimeInit.enableDdms();
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            // 读取配置文件传过来的数据,遍历匹配"start-system-server" 则要启动system server
            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.");
            }
            // ① 创建一个 Server 端的 Socket 通道
            registerZygoteSocket(socketName);
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            //② 预加载类和资源
            preload();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

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

            // Do an initial gc to clean up after startup
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
            gcAndFinalize();
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

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

            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();

            ZygoteHooks.stopZygoteNoThreadCreation();

            if (startSystemServer) {
                //③ 启动 system_server 进程,这样系统的服务也会由 system_server 进程启动起来。
                startSystemServer(abiList, socketName);
            }

            Log.i(TAG, "Accepting command socket connections");
           //④ 调用 此方法来等待 AMS 创建新进程的请求。
            runSelectLoop(abiList);

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

由以上可知,ZygoteInit.main 方法中主要做了 4 件事情:
① 创建 Server 端的 Socket ,用于响应 ActivityManagerService 创建新的应用进程的请求;
② 预加载类和资源;
③ 启动 system_server 进程,这样系统服务也就会由 system_server 启动起来;
④ 等待 ActivityManagerService 创建新的应用程序进程的请求;

创建一个 Server 端的 Socket 通道,用于响应ActivityManagerService 请求 Zygote 来创建新的应用程序进程的请求。

     /**
     * 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;
            try {
                String env = System.getenv(fullSocketName);·
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                sServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

启动系统服务:为系统服务器进程准备参数和fork。

    /**
     * Prepare the arguments and fork for the system server process.
     */ 
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
       ...
        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(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
       /* For child process 当前运行在 system_server 进程中 */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

system_server 进程复制了 Zygote 进程的地址空间,因此也会得到 Zygote 进程创建的 Socket,这个 Socket 对于 system_server 进程没有任何用处,因此,需要在关闭 Zygote 进程创建的 Socket,

   /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
        // 关闭 Zygote 进程创建的 Socket
        closeServerSocket();

      ...
        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) {
                ...
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createSystemServerClassLoader(systemServerClasspath,
                                                   parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            // 将其余参数传递给SystemServer,以便启动SystemServer用到
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

   /**
     * Creates a PathClassLoader for the system server. It also creates
     * a shared namespace associated with the classloader to let it access
     * platform-private native libraries.
     */
    private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
                                                                 int targetSdkVersion) {
      String librarySearchPath = System.getProperty("java.library.path");

      return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
                                                      librarySearchPath,
                                                      null /* libraryPermittedPath */,
                                                      ClassLoader.getSystemClassLoader(),
                                                      targetSdkVersion,
                                                      true /* isNamespaceShared */);
    }

在RuntimeInit.java 中的zygoteInit方法里面:nativeZygoteInit() 方法调用的是 Native 层的代码,用来启动 Binder 线程池,这样 ,system_server 进程就可以使用 Binder 与其他进程进行通信。applicationInit()方法是用于进入 system_server 的 main 方法。

// 路径:com.android.internal.os.RuntimeInit.java
  /**
     * The main function called when started through the zygote process. This
     * could be unified with main(), if the native code in nativeFinishInit()
     * were rationalized with Zygote startup.<p>
     *
     * Current recognized args:
     * <ul>
     *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
     * </ul>
     *
     * @param targetSdkVersion target SDK version
     * @param argv arg strings
     */
    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();

        commonInit();
        // 启动 Binder 线程池
        nativeZygoteInit();
      // 进入 system_server 的 main 方法
        applicationInit(targetSdkVersion, argv, classLoader);
    }

1 启动 Binder 线程池

ZygoteInit.nativeZygoteInit() 是一个 Native 方法,首先要了解它对应的 JNI 文件,如下所示:

// 路径:/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntime 是 AndroidRuntime 类型的指针,具体指向的是 AndroidRuntime 的子类 AppRuntime,在 app_main.cpp 中定义。接着来看 AppRuntime.onZygoteInit 方法,代码如下所示:

// 路径:/cmds/app_process/app_main.cpp
    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        // 启动一个 Binder 线程池,这样 system_server 进程就可以使用 Binder 与其他进程通信了。因此,从这里可以知道 ZygoteInit.nativeZygoteInit() 函数主要是用来启动 Binder 线程池的。
        proc->startThreadPool();
    }

2 进入 SystemServer.main 方法

// 路径:com.android.internal.os.RuntimeInit.java
    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
       ...
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

    /**
     * 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 {
            // 通过反射得到 SystemServer 类
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
           // 找到 SystemServer 的 main 方法
            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.
         */
        // 将找到的 main 方法传入到MethodAndArgsCaller构造方法中
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

ZygoteInit.main 方法中会在try catch中获取 MethodAndArgsCaller 对象,并调用 MethodAndArgsCaller.run() 方法。MethodAndArgsCaller 是 Zygote 的静态内部类:

// 路径:/core/java/com/android/internal/os/ZygoteInit.java
    public static void main(String argv[]) {
        ...
        try {
           ...
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            ...
            throw ex;
        }
    }

Zygote 中的MethodAndArgsCaller 静态内部类

   /**
     * Helper exception class which holds a method and arguments and
     * can call them. This is used as part of a trampoline to get rid of
     * the initial process setup stack frames.
     */
    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 {
                // 此处会被动态调用SystemServer.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);
            }
        }
    }

3 解析 system_server 进程

// 路径:/services/java/com/android/server/SystemServer.java 
    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }

    private void run() {
        try {
           ...
            Looper.prepareMainLooper();
            Looper.getMainLooper().setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

            // Initialize native services.
            // 1 加载了动态库 libandroid_servers.so
            System.loadLibrary("android_servers");
            ...
            // Initialize the system context.
            //  创建系统的 Context
            createSystemContext();

            // Create the system service manager.
            // 2  创建SystemServiceManager
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            // 3 启动引导服务
            startBootstrapServices();
            // 4 启动核心服务
            startCoreServices();
            // 5 启动其他服务
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        ...
        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

总结:
① 在注释 1 加载了动态库 libandroid_servers.so。
② 在注释 2 处创建 SystemServiceManager,它会对系统服务进行创建、启动和生命周期管理。
③ 在注释 3 处的 startBootstrapServices() 方法中回用 SystemServiceManager 启动 ActivityManagerService、PowerManagerService、PackageManagerService 等服务。
④ 在注释 4 处的 startCoreServices() 方法中则启动 DropBoxManagerService、BatteryService、UsageStateService 和 WebViewUpdateService。
⑤ 在注释 5 处的 startOtherServices() 方法中启动了 CameraService、AlarmManagerService、VrManagerService 等服务。
⑥ 从注释 3 、4、5 处可以 看出, 官方把系统服务分为三种类型,分别是引导服务、核心服务和其他服务,其中,其他服务是一些非要紧的和不需要立即启动的服务。 系统服务总共 100 多个,以下是其中的部分服务:

系统服务

6. 在 system_server 进程中会启动 AMS、WMS、PMS 等服务,等这些服务启动之后,AMS 中就会打开 Launcher 应用的 home Activity,最终就看到了手机的 “桌面”。


常见面试题

面试官:你了解 Android 系统启动流程吗?
程序员B
1、当按电源键触发开机,首先会从 ROM 中预定义的地方加载引导程序 BootLoader 到 RAM 中。
2、并执行 BootLoader 程序启动 Linux Kernel,
3、然后启动用户级别的第一个进程:init 进程。
4、init 进程会解析 init.rc 脚本做一些初始化工作,包括挂载文件系统、创建工作目录以及启动系统服务进程等,其中系统服务进程包括 Zygote、service manager、media 等。
5、在 Zygote 中会进一步去启动 system_server 进程,然后在 system_server 进程中会启动 AMS、WMS、PMS 等服务,
6、等这些服务启动之后,AMS 中就会打开 Launcher 应用的 home Activity,最终就看到了手机的 “桌面”。

面试官:system_server 为什么要在 Zygote 中启动,而不是由 init 直接启动呢?
程序员B:Zygote 作为一个孵化器,可以提前加载一些资源,这样 fork() 时基于 Copy-On-Write 机制创建的其他进程就能直接使用这些资源,而不用重新加载。比如 system_server 就可以直接使用 Zygote 中的 JNI 函数、共享库、常用的类、以及主题资源。

面试官:为什么要专门使用 Zygote 进程去孵化应用进程,而不是让 system_server 去孵化呢?
程序员B:首先 system_server 相比 Zygote 多运行了 AMS、WMS 等服务,这些对一个应用程序来说是不需要的。另外进程的 fork() 对多线程不友好,仅会将发起调用的线程拷贝到子进程,这可能会导致死锁,而 system_server 中肯定是有很多线程的。

面试官:能说说具体是怎么导致死锁的吗?
程序员B:fork() 时只会把调用线程拷贝到子进程、其他线程都会立即停止,那如果一个线程在 fork() 前占用了某个互斥量,fork() 后被立即停止,这个互斥量就得不到释放,再去请求该互斥量就会发生死锁了。

面试官:Zygote 为什么不采用 Binder 机制进行 IPC 通信?
程序员B:Binder 机制的 Binder 线程池是多线程的,如果采用的话就存在上面说的死锁问题了。
其实严格来说,Binder 机制不一定要多线程,所谓的 Binder 线程只不过是在循环读取 Binder 驱动的消息而已,只注册一个 Binder 线程也是可以工作的,比如 service manager 就是这样的。
尽管 Zygote 没有采取 Binder 机制,它也不是单线程的,内部还跑了一些虚拟机相关的守护线程,但它在 fork() 前主动停止了其他线程,fork() 后再重新启动。

参考:
Android系统启动(一)— init 进程启动过程
Android系统启动(二) — Zygote进程启动过程
Android系统启动(三) — SystemServer处理过程
Android系统启动(四) — Launcher 启动过程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容