zoukankan      html  css  js  c++  java
  • Android之 系统启动流程

    在前一篇文章"Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)"中,我们谈到“马达等系统服务都是通过SystemServer启动/管理的”。本章,我们就Android的系统启动流程进行分析;也说说SystemServer到底是如何工作的。

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3405100.html

    在详细说明之后,我们先建立个整体思路:
    Kernel中启动的第一个用户进程是init程序;而init会通过解析init.rc来启动zygote服务;而zygote又会进一步的启动SystemServer。在SystemServer中,Android会启动一系列的系统服务共用户调用。整个流程大致如此。下面,我们通过源码来查看一下各个环节到底是如何运作的。


    1. kernel启动init服务

    在Linux的内核init/main.c中,启动的/init程序。源码如下:

     1 static int __init kernel_init(void * unused)
     2 {
     3 
     4     ...
     5         
     6     // “设置第一个运行程序是/init”
     7     if (!ramdisk_execute_command)
     8         ramdisk_execute_command = "/init";
     9 
    10         ...
    11 
    12     init_post();
    13     return 0;
    14 }
    15 
    16 
    17 static noinline int init_post(void)
    18     __releases(kernel_lock)
    19 {
    20 
    21     ...
    22     // 运行"/init"程序
    23     if (ramdisk_execute_command) {
    24         run_init_process(ramdisk_execute_command);
    25         printk(KERN_WARNING "Failed to execute %s
    ",
    26                 ramdisk_execute_command);
    27     }
    28 
    29     ...
    30 
    31     run_init_process("/sbin/init");
    32     run_init_process("/etc/init");
    33     run_init_process("/bin/init");
    34     run_init_process("/bin/sh");
    35 
    36     ...
    37 }

    从中,我们发现:kernel_init()中会将ramdisk_execute_command的值初始化为"/init",进而在init_post()中调用run_init_process(),从而执行"/init"程序。
    我们所说的kernel内核空间到用户空间启动的第一个init程序,实际上就是"/init"程序。

    2. init服务的定义

    2.1 init的配置文件

    Android系统中init程序对应的Android.mk所在路径:system/core/init/Android.mk。内容如下: 

     1 LOCAL_PATH:= $(call my-dir)
     2 include $(CLEAR_VARS)
     3 
     4 LOCAL_SRC_FILES:= 
     5     builtins.c 
     6     init.c 
     7     devices.c 
     8     property_service.c 
     9     util.c 
    10     parser.c 
    11     logo.c 
    12     keychords.c 
    13     signal_handler.c 
    14     init_parser.c 
    15     ueventd.c 
    16     ueventd_parser.c 
    17     watchdogd.c
    18 
    19 LOCAL_MODULE:= init
    20 
    21 include $(BUILD_EXECUTABLE)
    22 
    23 ...

    说明: 在“完整的编译Android系统” 或 “对init执行模块编译(即$ mmm system/core/init)”的时候,会在system下生产文件out/.../root/init。"/root/init"意味着init在rootfs文件系统下,而不是system文件系统下。这也意味着,init会被解压到系统的根目录,即对应/init文件!

    2.2 init的程序入口

    init程序的入口函数main()定义在system/core/init/init.c中,源码如下:

     1 int main(int argc, char **argv)
     2 {
     3 
     4     ...
     5 
     6     // 创建目录
     7     mkdir("/dev", 0755);
     8     mkdir("/proc", 0755);
     9     mkdir("/sys", 0755);
    10 
    11     mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    12     mkdir("/dev/pts", 0755);
    13     mkdir("/dev/socket", 0755);
    14     mount("devpts", "/dev/pts", "devpts", 0, NULL);
    15     mount("proc", "/proc", "proc", 0, NULL);
    16     mount("sysfs", "/sys", "sysfs", 0, NULL);
    17 
    18     ...
    19 
    20     init_parse_config_file("/init.rc");
    21 
    22     ...
    23 }

    说明在init程序中,我们会进行一些列的初始化,包括创建目录,解析"init.rc"文件,启动相应的系统服务和守护进程等。zygote服务定义在init.rc中,它是在init中启动的。

    3. init启动解析init.rc,并启动zygote

    init.rc的路径:system/core/rootdir/init.rc。zygote在init.rc中的定义如下:

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

    从中,我们知道:zygote是service名称,而/system/bin/app_process是zygote对应的进程。后面的内容是service的参数。

    4. zygote服务

    4.1 zygote服务的配置文件

    通过init.rc中zygote的定义,我们知道zygote对应是通过/system/bin/app_process是启动的。app_process对应的Android.mk的路径:frameworks/base/cmds/app_process/Android.mk。它的内容如下:

     1 LOCAL_PATH:= $(call my-dir)
     2 include $(CLEAR_VARS)
     3 
     4 LOCAL_SRC_FILES:= 
     5     app_main.cpp
     6 
     7 LOCAL_SHARED_LIBRARIES := 
     8     libcutils 
     9     libutils 
    10     libbinder 
    11     libandroid_runtime
    12 
    13 LOCAL_MODULE:= app_process
    14 
    15 include $(BUILD_EXECUTABLE)

    从中,我们知道/system/bin/app_process会执行app_main.cpp。

    4.2 zygote对应的程序app_main.app

    app_main.cpp的入口main()源码如下:

     1 int main(int argc, const char* const argv[])
     2 {
     3     // These are global variables in ProcessState.cpp
     4     mArgC = argc;
     5     mArgV = argv;
     6 
     7     mArgLen = 0;
     8     for (int i=0; i<argc; i++) {
     9         mArgLen += strlen(argv[i]) + 1;
    10     }
    11     mArgLen--;
    12 
    13     AppRuntime runtime;
    14     const char* argv0 = argv[0];
    15 
    16     // Process command line arguments
    17     // ignore argv[0]
    18     argc--;
    19     argv++;
    20 
    21     // Everything up to '--' or first non '-' arg goes to the vm
    22 
    23     int i = runtime.addVmArguments(argc, argv);
    24 
    25     // Parse runtime arguments.  Stop at first unrecognized option.
    26     bool zygote = false;
    27     bool startSystemServer = false;
    28     bool application = false;
    29     const char* parentDir = NULL;
    30     const char* niceName = NULL;
    31     const char* className = NULL;
    32     // 解析参数
    33     while (i < argc) {
    34         const char* arg = argv[i++];
    35         if (!parentDir) {
    36             parentDir = arg;
    37         } else if (strcmp(arg, "--zygote") == 0) {
    38             // 设置zygote为true
    39             zygote = true;
    40             niceName = "zygote";
    41         } else if (strcmp(arg, "--start-system-server") == 0) {
    42             // 设置startSystemServer为true
    43             startSystemServer = true;
    44         } else if (strcmp(arg, "--application") == 0) {
    45             application = true;
    46         } else if (strncmp(arg, "--nice-name=", 12) == 0) {
    47             niceName = arg + 12;
    48         } else {
    49             className = arg;
    50             break;
    51         }
    52     }
    53 
    54     if (niceName && *niceName) {
    55         setArgv0(argv0, niceName);
    56         set_process_name(niceName);
    57     }
    58 
    59     runtime.mParentDir = parentDir;
    60 
    61     if (zygote) {
    62         // 启动"com.android.internal.os.ZygoteInit"
    63         runtime.start("com.android.internal.os.ZygoteInit",
    64                 startSystemServer ? "start-system-server" : "");
    65     } else if (className) {
    66         // Remainder of args get passed to startup class main()
    67         runtime.mClassName = className;
    68         runtime.mArgC = argc - i;
    69         runtime.mArgV = argv + i;
    70         runtime.start("com.android.internal.os.RuntimeInit",
    71                 application ? "application" : "tool");
    72     } else {
    73         fprintf(stderr, "Error: no class name or --zygote supplied.
    ");
    74         app_usage();
    75         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    76         return 10;
    77     }
    78 }

    从中,我们可以知道main()最终会调用以下代码:

    runtime.start("com.android.internal.os.ZygoteInit",
            startSystemServer ? "start-system-server" : "");

    我们接着看start()的代码。start()的源码定义在frameworks/base/core/jni/AndroidRuntime.cpp中。

    runtime是AppRuntime成员。AppRuntime定义在app_main.cpp中,声明如下:

    class AppRuntime : public AndroidRuntime {
      ...
    }

    显然AppRuntime继承于AndroidRuntime。

    4. AndroidRuntime.cpp

    start()的源码如下:

      1 void AndroidRuntime::start(const char* className, const char* options)
      2 {
      3     ALOGD("
    >>>>>> AndroidRuntime START %s <<<<<<
    ",
      4             className != NULL ? className : "(unknown)");
      5 
      6     blockSigpipe();
      7 
      8     /*
      9      * 'startSystemServer == true' means runtime is obsolete and not run from
     10      * init.rc anymore, so we print out the boot start event here.
     11      */
     12     if (strcmp(options, "start-system-server") == 0) {
     13         /* track our progress through the boot sequence */
     14         const int LOG_BOOT_PROGRESS_START = 3000;
     15         LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
     16                        ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
     17     }
     18 
     19     const char* rootDir = getenv("ANDROID_ROOT");
     20     if (rootDir == NULL) {
     21         rootDir = "/system";
     22         if (!hasDir("/system")) {
     23             LOG_FATAL("No root directory specified, and /android does not exist.");
     24             return;
     25         }
     26         setenv("ANDROID_ROOT", rootDir, 1);
     27     }
     28 
     29     //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
     30     //ALOGD("Found LD_ASSUME_KERNEL='%s'
    ", kernelHack);
     31 
     32     /* start the virtual machine */
     33     JNIEnv* env;
     34     if (startVm(&mJavaVM, &env) != 0) {
     35         return;
     36     }
     37     onVmCreated(env);
     38 
     39     /*
     40      * Register android functions.
     41      */
     42     if (startReg(env) < 0) {
     43         ALOGE("Unable to register all android natives
    ");
     44         return;
     45     }
     46 
     47     /*
     48      * We want to call main() with a String array with arguments in it.
     49      * At present we have two arguments, the class name and an option string.
     50      * Create an array to hold them.
     51      */
     52     jclass stringClass;
     53     jobjectArray strArray;
     54     jstring classNameStr;
     55     jstring optionsStr;
     56 
     57     stringClass = env->FindClass("java/lang/String");
     58     assert(stringClass != NULL);
     59     strArray = env->NewObjectArray(2, stringClass, NULL);
     60     assert(strArray != NULL);
     61     classNameStr = env->NewStringUTF(className);
     62     assert(classNameStr != NULL);
     63     env->SetObjectArrayElement(strArray, 0, classNameStr);
     64     optionsStr = env->NewStringUTF(options);
     65     env->SetObjectArrayElement(strArray, 1, optionsStr);
     66 
     67     /*
     68      * Start VM.  This thread becomes the main thread of the VM, and will
     69      * not return until the VM exits.
     70      */
     71     // 将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"
     72     char* slashClassName = toSlashClassName(className);
     73     // 获取"com/android/internal/os/ZygoteInit"对应的class对象
     74     jclass startClass = env->FindClass(slashClassName);
     75     if (startClass == NULL) {
     76         ALOGE("JavaVM unable to locate class '%s'
    ", slashClassName);
     77         /* keep going */
     78     } else {
     79         // 找到"com/android/internal/os/ZygoteInit"中main()方法的methodID
     80         jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
     81             "([Ljava/lang/String;)V");
     82         if (startMeth == NULL) {
     83             ALOGE("JavaVM unable to find main() in '%s'
    ", className);
     84             /* keep going */
     85         } else {
     86             // 执行"com/android/internal/os/ZygoteInit"中main()方法
     87             env->CallStaticVoidMethod(startClass, startMeth, strArray);
     88 
     89 #if 0
     90             if (env->ExceptionCheck())
     91                 threadExitUncaughtException(env);
     92 #endif
     93         }
     94     }
     95     free(slashClassName);
     96 
     97     ALOGD("Shutting down VM
    ");
     98     if (mJavaVM->DetachCurrentThread() != JNI_OK)
     99         ALOGW("Warning: unable to detach main thread
    ");
    100     if (mJavaVM->DestroyJavaVM() != 0)
    101         ALOGW("Warning: VM did not shut down cleanly
    ");
    102 }
    View Code

    说明start()是通过JNI回调java层的方法,它主要的目的是执行"com/android/internal/os/ZygoteInit"中main()方法,即frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中的main()函数。

    5. ZygoteInit.java

    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中的main()源码如下:

     1 public static void main(String argv[]) {
     2     try {
     3         // Start profiling the zygote initialization.
     4         SamplingProfilerIntegration.start();
     5 
     6         registerZygoteSocket();
     7         EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
     8             SystemClock.uptimeMillis());
     9         preload();
    10         EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
    11             SystemClock.uptimeMillis());
    12 
    13         // Finish profiling the zygote initialization.
    14         SamplingProfilerIntegration.writeZygoteSnapshot();
    15 
    16         // Do an initial gc to clean up after startup
    17         gc();
    18 
    19         // If requested, start system server directly from Zygote
    20         if (argv.length != 2) {
    21             throw new RuntimeException(argv[0] + USAGE_STRING);
    22         }
    23 
    24         if (argv[1].equals("start-system-server")) {
    25             // 调用startSystemServer()
    26             startSystemServer();
    27         } else if (!argv[1].equals("")) {
    28             throw new RuntimeException(argv[0] + USAGE_STRING);
    29         }
    30 
    31         Log.i(TAG, "Accepting command socket connections");
    32 
    33         if (ZYGOTE_FORK_MODE) {
    34             runForkMode();
    35         } else {
    36             runSelectLoopMode();
    37         }
    38 
    39         closeServerSocket();
    40     } catch (MethodAndArgsCaller caller) {
    41         caller.run();
    42     } catch (RuntimeException ex) {
    43         Log.e(TAG, "Zygote died with exception", ex);
    44         closeServerSocket();
    45         throw ex;
    46     }
    47 }
    View Code

    说明:main()会执行startSystemServer()来启动系统服务。

    startSystemServer()也是定义在ZygoteInit.java中,源码如下:

     1 private static boolean startSystemServer()
     2         throws MethodAndArgsCaller, RuntimeException {
     3     /* Hardcoded command line to start the system server */
     4     String args[] = {
     5         "--setuid=1000",
     6         "--setgid=1000",
     7         "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
     8         "--capabilities=130104352,130104352",
     9         "--runtime-init",
    10         "--nice-name=system_server",
    11         "com.android.server.SystemServer",
    12     };
    13     ZygoteConnection.Arguments parsedArgs = null;
    14 
    15     int pid;
    16 
    17     try {
    18         parsedArgs = new ZygoteConnection.Arguments(args);
    19         ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
    20         ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
    21 
    22         /* Request to fork the system server process */
    23         pid = Zygote.forkSystemServer(
    24                 parsedArgs.uid, parsedArgs.gid,
    25                 parsedArgs.gids,
    26                 parsedArgs.debugFlags,
    27                 null,
    28                 parsedArgs.permittedCapabilities,
    29                 parsedArgs.effectiveCapabilities);
    30     } catch (IllegalArgumentException ex) {
    31         throw new RuntimeException(ex);
    32     }
    33 
    34     /* For child process */
    35     if (pid == 0) {
    36         handleSystemServerProcess(parsedArgs);
    37     }
    38 
    39     return true;
    40 }

    说明
         startSystemServer()会通过Zygote.forkSystemServer()函数来创建一个新的进程来启动SystemServer组件,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess()函数。 

    handleSystemServerProcess()也是定义在ZygoteInit.java中,源码如下:

     1 private static void handleSystemServerProcess(
     2         ZygoteConnection.Arguments parsedArgs)
     3         throws ZygoteInit.MethodAndArgsCaller {
     4 
     5     closeServerSocket();
     6 
     7     // set umask to 0077 so new files and directories will default to owner-only permissions.
     8     Libcore.os.umask(S_IRWXG | S_IRWXO);
     9 
    10     if (parsedArgs.niceName != null) {
    11         Process.setArgV0(parsedArgs.niceName);
    12     }
    13 
    14     if (parsedArgs.invokeWith != null) {
    15         WrapperInit.execApplication(parsedArgs.invokeWith,
    16                 parsedArgs.niceName, parsedArgs.targetSdkVersion,
    17                 null, parsedArgs.remainingArgs);
    18     } else {
    19         /*
    20          * Pass the remaining arguments to SystemServer.
    21          */
    22         RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
    23     }
    24 
    25     /* should never reach here */
    26 }
    View Code

    说明handleSystemServerProcess()会调用 RuntimeInit.zygoteInit()器初始化zygote。

    6. RuntimeInit.java

    zygoteInit()定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java中,源码如下:

     1 public static final void zygoteInit(int targetSdkVersion, String[] argv)
     2         throws ZygoteInit.MethodAndArgsCaller {
     3     if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
     4 
     5     redirectLogStreams();
     6 
     7     commonInit();
     8     nativeZygoteInit();
     9 
    10     // 通过applicationInit()启动SystemServer
    11     applicationInit(targetSdkVersion, argv);
    12 }

    说明:zygoteInit()会调用applicationInit()函数初始化应用程序SystemServer。

    applicationInit()也定义在RuntimeInit.java中,源码如下:

     1 private static void applicationInit(int targetSdkVersion, String[] argv)
     2         throws ZygoteInit.MethodAndArgsCaller {
     3     nativeSetExitWithoutCleanup(true);
     4 
     5     VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
     6     VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
     7 
     8     final Arguments args;
     9     try {
    10         args = new Arguments(argv);
    11     } catch (IllegalArgumentException ex) {
    12         Slog.e(TAG, ex.getMessage());
    13         // let the process exit
    14         return;
    15     }
    16 
    17     // invokeStaticMain()会执行SystemServer的main()方法。
    18     invokeStaticMain(args.startClass, args.startArgs);
    19 }

    说明:applicationInit()会调用invokeStaticMain()来执行SystemServer的main()方法。

    invokeStaticMain()也定义在RuntimeInit.java中,源码如下:

     1 private static void invokeStaticMain(String className, String[] argv)
     2         throws ZygoteInit.MethodAndArgsCaller {
     3     Class<?> cl;
     4 
     5     try {
     6         // 根据“反射”查找SystemServer对应的Class
     7         cl = Class.forName(className);
     8     } catch (ClassNotFoundException ex) {
     9         throw new RuntimeException(
    10                 "Missing class when invoking static main " + className,
    11                 ex);
    12     }
    13 
    14     Method m;
    15     try {
    16         // 获取SystemServer对应的main()方法
    17         m = cl.getMethod("main", new Class[] { String[].class });
    18     } catch (NoSuchMethodException ex) {
    19         throw new RuntimeException(
    20                 "Missing static main on " + className, ex);
    21     } catch (SecurityException ex) {
    22         throw new RuntimeException(
    23                 "Problem getting static main on " + className, ex);
    24     }
    25 
    26     int modifiers = m.getModifiers();
    27     if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
    28         throw new RuntimeException(
    29                 "Main method is not public and static on " + className);
    30     }
    31 
    32     // 通过ZygoteInit.MethodAndArgsCaller()执行该main()方法
    33     throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    34 }

    说明
        首先,我们要搞清楚invokeStaticMain()的输入参数className,实际上它的值是"com.android.server.SystemServer"。
                  我们看从startSystemServer()方法中的args成员开始查看,在args通过ZygoteConnection.Arguments(args)解析之后得到parsedArgs对象;其中,parsedArgs.remainingArgs就是"com.android.server.SystemServer"。。
        接着,parseArgs传递给handleSystemServerProcess();
       再接着,将parsedArgs.remainingArgs,也就是"com.android.server.SystemServer"传递给了RuntimeInit.zygoteInit()。

    7. ZygoteInit.MethodAndArgsCaller

    MethodAndArgsCaller是一个实现了Runnable的类,它定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中。源码如下:

     1 public static class MethodAndArgsCaller extends Exception
     2         implements Runnable {
     3     private final Method mMethod;
     4 
     5     private final String[] mArgs;
     6 
     7     public MethodAndArgsCaller(Method method, String[] args) {
     8         mMethod = method;
     9         mArgs = args;
    10     }
    11 
    12     public void run() {
    13         try {
    14             // 通过反射,执行方法mMethod
    15             mMethod.invoke(null, new Object[] { mArgs });
    16         } catch (IllegalAccessException ex) {
    17             throw new RuntimeException(ex);
    18         } catch (InvocationTargetException ex) {
    19             Throwable cause = ex.getCause();
    20             if (cause instanceof RuntimeException) {
    21                 throw (RuntimeException) cause;
    22             } else if (cause instanceof Error) {
    23                 throw (Error) cause;
    24             }
    25             throw new RuntimeException(ex);
    26         }
    27     }
    28 }

    说明:MethodAndArgsCaller()是个线程,它会执行方法mMethod。也就是执行"com.android.server.SystemServer"中的main()方法。
    至此,我们就启动了SystemServer了!

  • 相关阅读:
    一行代码更改博客园皮肤
    fatal: refusing to merge unrelated histories
    使用 netcat 传输大文件
    linux 命令后台运行
    .net core 使用 Nlog 配置文件
    .net core 使用 Nlog 集成 exceptionless 配置文件
    Mysql不同字符串格式的连表查询
    Mongodb between 时间范围
    VS Code 使用 Debugger for Chrome 调试vue
    css权重说明
  • 原文地址:https://www.cnblogs.com/skywang12345/p/3405100.html
Copyright © 2011-2022 走看看