在前一篇文章"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了!