Android系统启动流程

时间:2021-06-30 16:45:03

系统启动流程

我们知道,Android系统是基于Linux改造出来的,所以继承了Linux很多特性,包括进程管理。在系统启动过程中,第一个启动的进程是Init进程,后面所有Fork出来的进程都是它的子孙后代,包括跟Android紧密联系的Zygote进程也是Init进程衍生的。

1、系统启动前期-Init进程

当按下开机按钮后,系统启动开始挂载设备,初始化Init进程,其中入口函数里,解析了一个叫做init.rc脚本程序,里面运用脚本命令启动了Zygote进程

2、Android的受精卵阶段-Zygote进程

fork出Zygote进程,执行了c++程序frameworks/base/cmds/app_process/app_main.cpp,该程序
是被cmd启动的,它做了一件主要的事情,初始化AppRuntime 对象,它负责启动java层的ZygoteInit类的main入口函数。代码如下:

int main(int argc, char* const argv[])
{
    ...
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//1
    } 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;
    }
}

从底层眼看要来到Java层了,AppRuntime是还做了另外一个更有趣的事情。在启动运行Java文件之前肯定要有Davilk虚拟机,所以在这里会先调用startVm()来启动Davilk虚拟机-DVM。然后在cpp层调用拿到ZygoteInit类,调用CallStaticVoidMethod()来启动了com.android.internal.os.ZygoteInit的main函数。里面调用了runtime对象的start()方法传入ZygoteInit类名创建,代码如下:

/*
 * 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".
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    static const String8 startSystemServer("start-system-server");
    //启动VM
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);


    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);
    ...省略若干行...

    /*
     * 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 {
        //拿到方法对应的id
        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 {
            //调用main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

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

}

3、完成使命,进入胚胎时期ZygoteInit.java -> SystemServer.java

1.在这时候,跟Java有关的第一个进程Zygote进程启动了,在main函数里,它建立了一个socket通讯服务端,通过文件描述符 /dev/socket/zygote 初始化LocalServerSocket服务端,这个服务端后面会跟AMS(ActivityManagerService)来建立socket通讯,初始化然后接着调用startSystemServer()启动SystemServer进程,然后调用runSelectLoopMode()等待AMS的连接.

public static void main(String argv[]) {
        try {
            //。。。省略n行。。。
            1.建立ActivityManagerService(据说,求举证)连接
            registerZygoteSocket(socketName);

            //。。。省略n行。。。
            2.启动SystemServer.java
            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }
            //。。。省略n行。。。
            //执行死循环等待连接
            3.runSelectLoopMode()
            //
            4.关闭连接
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            closeServerSocket();
            throw ex;
        }
    }

tips:为什么这里用socket通讯而不用Binder? 因为还没有启动,在接下来的Systemserver启动时会启动Binder机制。

在startSystemServer中,调用了Zygote.forSystemServer()来fork出新的进程,叫SystemServer进程.

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
               /* 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,1021,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "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(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        //...

        return true;
    }
    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

具体怎么fork出来的呢,可以看到调用了nativeForkSystemServer()的native方法.具体的实现在:/dalvik/vm/native/dalvik_system_Zygote.cpp,具体的实现forkSystemServer()方法中,做了两个事

1.调用forkAndSpecializeCommon()
2.杀死Zygote进程自己,脱壳退场.

const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
    { "nativeFork", "()I",
      Dalvik_dalvik_system_Zygote_fork },
    { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
      Dalvik_dalvik_system_Zygote_forkAndSpecialize },
    { "nativeForkSystemServer", "(II[II[[IJJ)I",
      Dalvik_dalvik_system_Zygote_forkSystemServer },
    { NULL, NULL, NULL },
};
/*
 * native public static int nativeForkSystemServer(int uid, int gid,
 *     int[] gids, int debugFlags, int[][] rlimits,
 *     long permittedCapabilities, long effectiveCapabilities);
 */
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
        const u4* args, JValue* pResult)
{
    pid_t pid;
    pid = forkAndSpecializeCommon(args, true);

    /* The zygote process checks whether the child process has died or not. */
    if (pid > 0) {
        int status;

        ALOGI("System server process %d has been created", pid);
        gDvm.systemServerPid = pid;
        /* There is a slight window that the system server process has crashed
         * but it went unnoticed because we haven't published its pid yet. So
         * we recheck here just to make sure that all is well.
         */
        if (waitpid(pid, &status, WNOHANG) == pid) {
            ALOGE("System server process %d has died. Restarting Zygote!", pid);
            kill(getpid(), SIGKILL);
        }
    }
    RETURN_INT(pid);
}

4、成功变成宝宝-SystemServer进程启动系统服务

Zygote进程fork出新的进程SystemServer了,完成了受精卵时期。来到另外一个万花筒年代.一个新的进程开始,按照旧惯例还是以main函数作为入口,里面直接粗暴的new了一个本类对象执行了run方法(社会社会)。

/** * The main entry point from zygote. */
    public static void main(String[] args) {
        new SystemServer().run();
    }

run方法里启动了三种服务

1.引导服务
startBootstrapServices();

2.核心服务
startCoreServices();

3.增值服务
startOtherServices();
主要逻辑部分代码如下:

// Initialize the system context.

        createSystemContext();

        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

        // Start services.
        try {
            //1.引导服务
            startBootstrapServices();
            //2.核心服务
            startCoreServices();
            //3增值服务
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

AMS是第一个被启动的,当他以及一系列服务(WindowManagerService、PackageManagerService…)启动执行被启动后(迎接第一个高潮),接下来AMS就去干两件非常重要的事情,就是去告诉邻居和开门。
1.AMS会启动桌面程序Launcher。
2.接着会通知SurfaceFlinger关闭它的bootanimation(开机的时候启动开机动画)。这时候桌面就会显示出来了。

总结一下:

1.系统挂载和Init进程初始化

3.在里面appruntime对象启动Davilk并fork出Zygote进程

4.受精卵建立socket服务端等待AMS连接。同时并fork一个子进程出来启动SystemServer

5.SystemServer启动各种服务,其中包括AMS,和其他系统服务。AMS启动后会连接Zygote进程。然后启动Launcher和关闭开机动画。
6.调用各种服务起来之后纷纷调用各自的systemReady()方法;接下来的关心的事情就是:Launcher的启动流程

(后面将分享Binder进程间通讯的机制&Launcher的启动流程)