在前一篇文章"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.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.\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 }
说明: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 }
说明: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 }
说明: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了!