文章出处:http://blog.csdn.net/shift_wwx
前言:之前android zygote之启动过程分析中分析了一下zygote启动的过程,其中涉及的重要部分有三个:一是创建了一个socket,方便了后期AMS与zygote的通讯,为什么一定要zygote通讯其实说白了就是zygote拥有的东西太多,需要分享一下它;二是启动了system_server进程,而这个进程就是用户基本所有service创建和启动的地方,也是android系统启动的关键一步;三是创建了一个loop,处理AMS发到zygote的一些进程处理信息。
@/frameworks/vase/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit { ...... public static void main(String argv[]) { try { ...... registerZygoteSocket(); ...... if (argv[1].equals("start-system-server")) { startSystemServer(); } else if (!argv[1].equals("")) { throw new RuntimeException(argv[0] + USAGE_STRING); } ...... runSelectLoop(); ...... } catch (MethodAndArgsCaller caller) { ...... }catch (RuntimeException ex) { ...... } } }
来看一下startSystemServer:
/** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_RESOURCE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG );//没看懂,POSIX接口性能? /* 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,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--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); /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { handleSystemServerProcess(parsedArgs); } return true; }详细分析:
1、args
下面会出现parsedArgs = new ZygoteConnection.Arguments(args);
处理过程是在:
@/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private void parseArgs(String args[]) throws IllegalArgumentException { ...... }
1)uid=1000
@/frameworks/base/core/java/android/os/Process.java
/** * Defines the UID/GID under which system code runs. */ public static final int SYSTEM_UID = 1000;还有其他特殊的uid定义:
/** * Defines the UID/GID under which the telephony code runs. */ public static final int PHONE_UID = 1001; /** * Defines the UID/GID for the user shell. * @hide */ public static final int SHELL_UID = 2000; /** * Defines the UID/GID for the log group. * @hide */ public static final int LOG_UID = 1007; /** * Defines the UID/GID for the WIFI supplicant process. * @hide */ public static final int WIFI_UID = 1010; ......2)gid=1000
3)niceName=system_server这里的niceName就是需要创建的进程名,系统起来ps会看到
4)remainingArgs = new String[args.length - curArg];生下来的应该就是args最后的,这边应该是SystemServer的类名
2、forkSystemServer
pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities);@/libcore/dalvik/src/main/java/dalvik/system/Zygote.java
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { preFork(); int pid = nativeForkSystemServer( uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities); postFork(); return pid; } native public static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);@/dalvik/vm/native/dalvik_system_Zygote.cpp
/* * native public static int nativeForkSystemServer(int uid, int gid, * int[] gids, int debugFlags, int[][] rlimits, * long permittedCapabilities, long effectiveCapabilities); */ static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult) { pid_t pid; 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); } } RETURN_INT(pid); }看一下forkAndSpecializeCommon(args, true);其实就是两句话:
dvmDumpLoaderStats("zygote"); pid = fork();
system_server就是由zygote fork而来的。
有点不明白,fork出来应该是子进程,pid应该是0,那么这个if是什么时候调用的呢?
应该是作为父进程的时候,会提示,然后对system_server做监控,出问题的时候,会kill掉system_server,然后restart zygote,需要确认一下。
这里有几篇好文章,可以参考一下。
在系统起来之后ps一下看看吧:
root 174 1 627992 19028 ffffffff 400d88f0 S zygote drm 175 1 12560 4908 ffffffff b6e9c7a4 S /system/bin/drmserver media 176 1 82836 27872 ffffffff b6e9d7a4 S /system/bin/mediaserver root 177 1 1004 220 c057e4b8 b6f344e0 S /system/bin/installd keystore 179 1 3372 1012 c038b40c b6ee77a4 S /system/bin/keystore root 180 1 1908 492 c00dde38 b6f898f0 S /system/bin/pppoe_wrapper root 181 1 61328 37876 ffffffff b6efa7a4 S /system/bin/imageserver media_rw 183 1 3528 440 ffffffff b6f4a4e0 S /system/bin/sdcard root 185 2 0 0 c0041a1c 00000000 S kworker/3:1H root 198 2 0 0 c0041a1c 00000000 S kworker/1:1H root 455 2 0 0 c039b180 00000000 S aml_buf_toggle system 508 174 732700 40224 ffffffff 400d9954 S system_server u0_a8 610 174 684360 61076 ffffffff 400d9954 S com.android.systemuisystem_server pid是508,ppid是174,而174确实是zygote进程
3、handleSystemServerProcess
/** * Finish remaining work for the newly forked system server process. */ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket(); // set umask to 0077 so new files and directories will default to owner-only permissions. Libcore.os.umask(S_IRWXG | 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 { /* * Pass the remaining arguments to SystemServer. */ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } /* should never reach here */ }由于由Zygote进程创建的子进程会继承Zygote进程中创建的Socket文件描述符,而这里的子进程又不会用到它,因此,这里就调用closeServerSocket函数来关闭它。这个函数接着调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操作。
public static final void zygoteInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); redirectLogStreams();//把system.out和system.err输出重定向到android log中 commonInit(); nativeZygoteInit(); applicationInit(targetSdkVersion, argv); }1)commonInit()
这里很关键哦,很多log中都会看到:
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; }第一句话加了一个异常捕获的handler:UncaughtHandler
private static class UncaughtHandler implements Thread.UncaughtExceptionHandler { public void uncaughtException(Thread t, Throwable e) { try { // Don't re-enter -- avoid infinite loops if crash-reporting crashes. if (mCrashing) return; mCrashing = true; if (mApplicationObject == null) { Slog.e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e); } else { StringBuilder message = new StringBuilder(); message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n"); final String processName = ActivityThread.currentProcessName(); if (processName != null) { message.append("Process: ").append(processName).append(", "); } message.append("PID: ").append(Process.myPid()); Slog.e(TAG, message.toString(), e); } // Bring up crash dialog, wait for it to be dismissed ActivityManagerNative.getDefault().handleApplicationCrash( mApplicationObject, new ApplicationErrorReport.CrashInfo(e)); } catch (Throwable t2) { try { Slog.e(TAG, "Error reporting crash", t2); } catch (Throwable t3) { // Even Slog.e() fails! Oh well. } } finally { // Try everything to make sure this process goes away. Process.killProcess(Process.myPid()); System.exit(10); } } }log中经常出现的FATAL EXCEPTION:***就是从这里来的
回到commonInit(),其他就是一些初始化,例如时区等
2)nativeZygoteInit
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); }看到这个onZygoteInit很是熟悉,在 android zygote之启动过程分析中涉及到:
AppRuntime runtime调用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了
private static void applicationInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { // If the application calls System.exit(), terminate the process // immediately without running any shutdown hooks. It is not possible to // shutdown an Android application gracefully. Among other things, the // Android runtime shutdown hooks close the Binder driver, which can cause // leftover running threads to crash before the process actually exits. nativeSetExitWithoutCleanup(true); // We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn't needed. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { Slog.e(TAG, ex.getMessage()); // let the process exit return; } // Remaining arguments are passed to the start class's static main invokeStaticMain(args.startClass, args.startArgs); }invokeStaticMain:
private static void invokeStaticMain(String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; try { cl = Class.forName(className); } catch (ClassNotFoundException ex) { throw new RuntimeException( "Missing class when invoking static main " + className, ex); } 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); } int modifiers = m.getModifiers(); 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); }这里会将systemserver的类名传进去,run是在ZygoteInit.main里面。
最终就会调用到SystemServer.main(),对于SystemServer后期也会继续分析。请参考android SystemServer详解