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\n",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.c18 19 LOCAL_MODULE:= init20 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_runtime12 13 LOCAL_MODULE:= app_process14 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 arguments17 // ignore argv[0]18 argc--;19 argv++;20 21 // Everything up to '--' or first non '-' arg goes to the vm22 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为true39 zygote = true;40 niceName = "zygote";41 } else if (strcmp(arg, "--start-system-server") == 0) {42 // 设置startSystemServer为true43 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.\n");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("\n>>>>>> AndroidRuntime START %s <<<<<<\n", 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'\n", 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\n"); 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'\n", 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'\n", 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\n"); 98 if (mJavaVM->DetachCurrentThread() != JNI_OK) 99 ALOGW("Warning: unable to detach main thread\n");100 if (mJavaVM->DestroyJavaVM() != 0)101 ALOGW("Warning: VM did not shut down cleanly\n");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 startup17 gc();18 19 // If requested, start system server directly from Zygote20 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()启动SystemServer11 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 exit14 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 // 通过反射,执行方法mMethod15 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了!
更多相关文章
- android studio 程序员有福了—从layout自动生成viewholder类
- Android自定义属性与自定义属性的获取
- 【Android】源码分析 - Handler消息机制再梳理
- Android中AsyncTask详解,源码剖析(API 23)
- [转]Android 应用程序基础(Application Fundamentals)
- Android下添加新的自定义键值和按键处理流程
- Android 5.1.1 源码目录结构
- Android中自定义控件