在上一篇文中介绍了Zygote进程的启动过程,我们知道,Zygote进程是Android Java世界的开创者,所有的Java应用程序进程都由Zygote进程创建。Zygote创建应用程序进程过程其实就是复制自身进程地址空间作为应用程序进程的地址空间,因此在Zygote进程中加载的类和资源都可以共享给所有由Zygote进程孵化的应用程序,应用程序进程只需加载自身私有资源就可以正常运行,Zygote进程是所有Android Java应用程序进程的父进程,Zygote进程和普通应用程序进程之间的关系正是面向对象编程语言中的继承关系,应用程序进程继承Zygote进程的所有资源,Zygote进程在启动时加载所有应用程序进程运行所需的公共资源,即应用程序运行的共性资源;由于普通应用程序有自己的特性资源,因此普通应用程序在启动时,只需要加载自身特性资源就可以了。Linux进程间这种继承关系加快了普通应用程序启动的速度,也简化了应用程序进程的创建过程。既然所有Java应用程序进程都是由Zygote进程创建,那么Android系统是如何请求Zygote进程创建一个新的应用程序进程的呢?在Zygote进程启动过程的源代码分析中,我们介绍了Zygote进程在启动过程中,会根据启动参数创建第一Java进程,它就是SystemServer进程,它是Android系统至关重要的进程,运行中Android系统的绝大部分服务。普通应用程序进程是无法直接请求Zygote进程孵化新进程的,所有的进程创建请求都是由SystemServer进程发出的。本文依据源码,详细分析SystemServer进程的启动过程。在Zygote进程进入循环监听Socket模式前,会根据Zygote启动参数来选择是否启动SystemServer进程,而Zygote进程的启动是在Android的启动脚本init.rc文件中配置的:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server由于配置了参数--start-system-server,因此SystemServer进程会伴随Zygote进程的启动而启动:
if (argv[1].equals("start-system-server")) { startSystemServer(); } else if (!argv[1].equals("")) { throw new RuntimeException(argv[0] + USAGE_STRING); }SystemServer虽然也是又Zygote进程孵化出来,但和普通的应用程序进程的启动方式有所不同,这里是通过调用startSystemServer()函数来启动SystemServer进程的。
private static boolean startSystemServer() 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,3001,3002,3003,3006,3007", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { //参数解析 parsedArgs = new ZygoteConnection.Arguments(args); //打开系统调试属性 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* 请求fork SystemServer进程*/ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* pid为0表示子进程,即SystemServer进程,从此SystemServer进程与Zygote进程分道扬镳*/ if (pid == 0) { handleSystemServerProcess(parsedArgs); } return true; }
在该函数中首先根据SystemServer进程启动参数args构造一个Arguments对象,然后调用forkSystemServer()函数创建SystemServer进程,最后调用函数handleSystemServerProcess()启动SystemServer进程,SystemServer启动参数如下:
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
参数解析
Arguments(String args[]) throws IllegalArgumentException { parseArgs(args); }在Arguments构造函数中直接调用parseArgs函数来解析SystemServer启动参数
private void parseArgs(String args[]) throws IllegalArgumentException { int curArg = 0; for ( /* curArg */ ; curArg < args.length; curArg++) { String arg = args[curArg]; if (arg.equals("--")) { curArg++; break; } else if (arg.startsWith("--setuid=")) { if (uidSpecified) { throw new IllegalArgumentException("Duplicate arg specified"); } uidSpecified = true; //解析setuid参数,将进程uid保存到变量uid中 uid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); } else if (arg.startsWith("--setgid=")) { if (gidSpecified) { throw new IllegalArgumentException("Duplicate arg specified"); } gidSpecified = true; //解析setgid参数,将进程gid保存到变量gid中 gid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); } else if (arg.startsWith("--target-sdk-version=")) { if (targetSdkVersionSpecified) { throw new IllegalArgumentException("Duplicate target-sdk-version specified"); } targetSdkVersionSpecified = true; targetSdkVersion = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); //根据参数设置debugFlags标志位 } else if (arg.equals("--enable-debugger")) { debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; } else if (arg.equals("--enable-safemode")) { debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; } else if (arg.equals("--enable-checkjni")) { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } else if (arg.equals("--enable-jni-logging")) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } else if (arg.equals("--enable-assert")) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } else if (arg.equals("--peer-wait")) { peerWait = true; } else if (arg.equals("--runtime-init")) { runtimeInit = true; } else if (arg.startsWith("--capabilities=")) { if (capabilitiesSpecified) { throw new IllegalArgumentException("Duplicate arg specified"); } capabilitiesSpecified = true; String capString = arg.substring(arg.indexOf('=')+1); String[] capStrings = capString.split(",", 2); if (capStrings.length == 1) { effectiveCapabilities = Long.decode(capStrings[0]); permittedCapabilities = effectiveCapabilities; } else { permittedCapabilities = Long.decode(capStrings[0]); effectiveCapabilities = Long.decode(capStrings[1]); } } else if (arg.startsWith("--rlimit=")) { // Duplicate --rlimit arguments are specifically allowed. String[] limitStrings= arg.substring(arg.indexOf('=')+1).split(","); if (limitStrings.length != 3) { throw new IllegalArgumentException("--rlimit= should have 3 comma-delimited ints"); } int[] rlimitTuple = new int[limitStrings.length]; for(int i=0; i < limitStrings.length; i++) { rlimitTuple[i] = Integer.parseInt(limitStrings[i]); } if (rlimits == null) { rlimits = new ArrayList(); } rlimits.add(rlimitTuple); } else if (arg.equals("-classpath")) { if (classpath != null) { throw new IllegalArgumentException("Duplicate arg specified"); } try { classpath = args[++curArg]; } catch (IndexOutOfBoundsException ex) { throw new IllegalArgumentException("-classpath requires argument"); } } else if (arg.startsWith("--setgroups=")) { if (gids != null) { throw new IllegalArgumentException("Duplicate arg specified"); } String[] params = arg.substring(arg.indexOf('=') + 1).split(","); gids = new int[params.length]; for (int i = params.length - 1; i >= 0 ; i--) { gids[i] = Integer.parseInt(params[i]); } } else if (arg.equals("--invoke-with")) { if (invokeWith != null) { throw new IllegalArgumentException("Duplicate arg specified"); } try { invokeWith = args[++curArg]; } catch (IndexOutOfBoundsException ex) { throw new IllegalArgumentException("--invoke-with requires argument"); } } else if (arg.startsWith("--nice-name=")) { if (niceName != null) { throw new IllegalArgumentException("Duplicate arg specified"); } niceName = arg.substring(arg.indexOf('=') + 1); } else { break; } } //参数-classpath 和 --runtime-init 不能同时设置 if (runtimeInit && classpath != null) { throw new IllegalArgumentException("--runtime-init and -classpath are incompatible"); } //保存剩余参数 remainingArgs = new String[args.length - curArg]; System.arraycopy(args, curArg, remainingArgs, 0,remainingArgs.length); }
属性配置
public static void applyDebuggerSystemProperty(Arguments args) { if ("1".equals(SystemProperties.get("ro.debuggable"))) { args.debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; } } public static void applyInvokeWithSystemProperty(Arguments args) { if (args.invokeWith == null && args.niceName != null) { //true if (args.niceName != null) { String property = "wrap." + args.niceName; //wrap.system_server if (property.length() > 31) { property = property.substring(0, 31); } args.invokeWith = SystemProperties.get(property); if (args.invokeWith != null && args.invokeWith.length() == 0) { args.invokeWith = null; } } } }
创建SystemServer进程
通过调用forkSystemServer函数来创建SystemServer进程
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { //停止Zygote进程中的其他线程,保证单线程 preFork(); int pid = nativeForkSystemServer(uid, gid, gids, debugFlags, rlimits,permittedCapabilities,effectiveCapabilities); //启动垃圾回收后台线程 postFork(); return pid; }
该函数调用native函数nativeForkAndSpecialize来fork出systemserver进程
native public static int nativeForkSystemServer(int uid, int gid,int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities); { "nativeForkSystemServer", "(II[II[[IJJ)I", Dalvik_dalvik_system_Zygote_forkSystemServer },
根据JNI函数映射关系,最终会调用C++的Dalvik_dalvik_system_Zygote_forkSystemServer函数,在dalvik_system_Zygote.c文件中实现:
static void Dalvik_dalvik_system_Zygote_forkSystemServer(const u4* args, JValue* pResult) { pid_t pid; //根据参数,fork一个子进程 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);*/ sleep(15); //如果SystemServer进程退出,zygote将杀死自身进程 #ifdef HOST_DALVIK reboot(RB_AUTOBOOT); #else android_reboot(ANDROID_RB_RESTART2, 0, (char *)"special-systemserver-died"); #endif } } RETURN_INT(pid); }
真正创建进程的核心函数:
static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) { .......... pid = fork(); //使用Linux 系统调用fork来创建进程 if (pid == 0) { //设置子进程的uid,gid等参数 } else if (pid > 0) { /* the parent process */ } return pid; }
创建好SystemServer进程后,继续调用preFork()来启动后台线程
private static void postFork() { Daemons.start(); //启动后台线程 }libcore\luni\src\main\java\java\lang\Daemons.java
public static void start() { //启动ReferenceQueueDaemon线程 ReferenceQueueDaemon.INSTANCE.start(); //启动FinalizerDaemon线程 FinalizerDaemon.INSTANCE.start(); //启动FinalizerWatchdogDaemon线程 FinalizerWatchdogDaemon.INSTANCE.start(); }
运行SystemServer进程
新创建的SystemServer进程会执行handleSystemServerProcess函数,来完成自己的使命。
private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { //因为SystemServer是从Zygote进程中复制过来的,所有需要关闭从zygote继承下来的socket closeServerSocket(); // set umask to 0077 so new files and directories will default to owner-only permissions. FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO); //设置进程名称 if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, null, parsedArgs.remainingArgs); } else { //传递剩余参数给SystemServer并调用zygoteInit函数 // "--nice-name=system_server com.android.server.SystemServer" RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } }由于由Zygote进程创建的子进程都会继承Zygote进程在前面创建的Socket文件描述符,而这里的SystemServer进程又不会用到它,因此,这里就调用closeServerSocket函数来关闭它。这个函数接着调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer
frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); //重定向Log输出流 redirectLogStreams(); //初始化运行环境 commonInit(); //启动Binder线程池 nativeZygoteInit(); //调用程序入口函数 applicationInit(targetSdkVersion, argv); }
1. 初始化Log输出流
/** * Redirect System.out and System.err to the Android log. */ public static void redirectLogStreams() { System.out.close(); System.setOut(new AndroidPrintStream(Log.INFO, "System.out")); System.err.close(); System.setErr(new AndroidPrintStream(Log.WARN, "System.err")); }
2.初始化运行环境
private static final void commonInit() { if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!"); /* set default handler; this applies to all threads in the VM */ Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()); /* * Install a TimezoneGetter subclass for ZoneInfo.db */ TimezoneGetter.setInstance(new TimezoneGetter() { @Override public String getId() { return SystemProperties.get("persist.sys.timezone"); } }); TimeZone.setDefault(null); /* * Sets handler for java.util.logging to use Android log facilities. * The odd "new instance-and-then-throw-away" is a mirror of how * the "java.util.logging.config.class" system property works. We * can't use the system property here since the logger has almost * certainly already been initialized. */ LogManager.getLogManager().reset(); new AndroidConfig(); /* * Sets the default HTTP User-Agent used by HttpURLConnection. */ String userAgent = getDefaultUserAgent(); System.setProperty("http.agent", userAgent); /* * Wire socket tagging to traffic stats. */ NetworkManagementSocketTagger.install(); /* * If we're running in an emulator launched with "-trace", put the * VM into emulator trace profiling mode so that the user can hit * F9/F10 at any time to capture traces. This has performance * consequences, so it's not something you want to do always. */ String trace = SystemProperties.get("ro.kernel.android.tracing"); if (trace.equals("1")) { Slog.i(TAG, "NOTE: emulator trace profiling enabled"); Debug.enableEmulatorTraceOutput(); } initialized = true; }
3.启动Binder线程池
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); }frameworks\base\cmds\app_process\App_main.cpp
virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); }关于Binder线程池的启动过程请参考 Android应用程序启动Binder线程源码分析
4.调用进程入口函数
static void invokeStaticMain(ClassLoader loader, String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { //加载"com.android.server.SystemServer"类 Class<?> cl; try { cl = loader.loadClass(className); } catch (ClassNotFoundException ex) { throw new RuntimeException("Missing class when invoking static main " + className, ex); } //通过类反射机制查找SystemServer类中的main函数 Method m; try { m = cl.getMethod("main", new Class[] { String[].class }); } catch (NoSuchMethodException ex) { throw new RuntimeException("Missing static main on " + className, ex); } catch (SecurityException ex) { throw new RuntimeException("Problem getting static main on " + className, ex); } //获取main函数的修饰符 int modifiers = m.getModifiers(); //进程入口函数必须为静态Public类型 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException("Main method is not public and static on " + className); } /* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */ throw new ZygoteInit.MethodAndArgsCaller(m, argv); }抛出MethodAndArgsCaller异常,并在ZygoteInit.main()函数中捕获该异常,这样就可以清除应用程序进程创建过程的调用栈,将应用程序启动的入口函数设置为SystemServer.main()
public static void main(String argv[]) { try { ... //捕获MethodAndArgsCaller异常 } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }在该函数里,捕获了MethodAndArgsCaller异常,并调用MethodAndArgsCaller类的run()方法来处理异常
public static class MethodAndArgsCaller extends Exception implements Runnable { public void run() { try { mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { Throwable cause = ex.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } throw new RuntimeException(ex); } } }这里通过反射机制调用SystemServer类的main函数
public static void main(String[] args) { if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { // If a device's clock is before 1970 (before 0), a lot of // APIs crash dealing with negative numbers, notably // java.io.File#setLastModified, so instead we fake it and // hope that time from cell towers or NTP fixes it // shortly. Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } //启动SamplingProfilerIntegration线程,并且每隔1小时写一次快照 if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } // Mmmmmm... more memory! dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); //加载libandroid_servers.so库 System.loadLibrary("android_servers"); //进入服务启动第一阶段:启动native服务 init1(args); }
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz) { system_init(); }frameworks\base\cmds\system_server\library\system_init.cpp
extern "C" status_t system_init() { ALOGI("Entered system_init()"); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); ALOGI("ServiceManager: %p\n", sm.get()); sp<GrimReaper> grim = new GrimReaper(); sm->asBinder()->linkToDeath(grim, grim.get(), 0); char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsurfaceflinger", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the SurfaceFlinger SurfaceFlinger::instantiate(); } property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the sensor service SensorService::instantiate(); } // And now start the Android runtime. We have to do this bit // of nastiness because the Android runtime initialization requires // some of the core system services to already be started. // All other servers should just start the Android runtime at // the beginning of their processes's main(), before calling // the init function. ALOGI("System server: starting Android runtime.\n"); AndroidRuntime* runtime = AndroidRuntime::getRuntime(); ALOGI("System server: starting Android services.\n"); JNIEnv* env = runtime->getJNIEnv(); if (env == NULL) { return UNKNOWN_ERROR; } //通过JNI调用SystemServer类的init2()函数,启动Java服务 jclass clazz = env->FindClass("com/android/server/SystemServer"); if (clazz == NULL) { return UNKNOWN_ERROR; } jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V"); if (methodId == NULL) { return UNKNOWN_ERROR; } env->CallStaticVoidMethod(clazz, methodId); //启动Binder线程池 ALOGI("System server: entering thread pool.\n"); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); ALOGI("System server: exiting thread pool.\n"); return NO_ERROR; }
public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); //通过启动ServerThread线程来启动Java服务 Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); }
public void run() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,SystemClock.uptimeMillis()); Looper.prepare(); android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND); BinderInternal.disableBackgroundScheduling(true); android.os.Process.setCanSelfBackground(false); .... ServiceManager.addService("entropy", new EntropyMixer()); ServiceManager.addService(Context.POWER_SERVICE, power); ServiceManager.addService("security", security); ServiceManager.addService("telephony.registry",new TelephonyRegistry(context, 0)); ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE,new SchedulingPolicyService()); .... //PowerManagerServer WakeLock dump thread (new Thread(new WakelockMonitor(power))).start(); // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); } Looper.loop(); Slog.d(TAG, "System ServerThread is exiting!"); }
在run函数中启动并注册Java中的各种Service。至此SystemServer进程启动过程分析完毕!启动过程序列图如下所示: