Zygote
进程是Android
和Java
世界的开创者。在android
系统中,全部的应用进程和SystemServer
进程都是由Zygote
进程fork
而来。其重要性因而可知一斑。虽然Zygote
进程至关于Android
系统的根进程,可是事实上它也是由Linux
系统的init
进程启动的。各个进程的前后顺序为:java
init
进程 –-> Zygote
进程 –> SystemServer
进程 –>应用进程linux
其中Zygote
进程由init
进程启动,SystemServer
进程和应用进程由Zygote
进程启动。本文依据6.0源码,主要分析Zygote
进程的启动流程。init
进程在启动Zygote
进程时会调用ZygoteInit#main()
。以此为切入点,一步步分析。android
源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java数组
ZygoteInit#main();app
public static void main(String argv[]) { try { // 设置DDMS可用 RuntimeInit.enableDdms(); // 初始化启动参数 boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } // 注册socket registerZygoteSocket(socketName); // 预加载各类资源 preload(); ... if (startSystemServer) { // 启动SystemServer进程 startSystemServer(abiList, socketName); } // 监听socket,启动新的应用进程。--后文会讲 runSelectLoop(abiList); closeServerSocket(); } catch (MethodAndArgsCaller caller) { // 经过反射调用SystemServer#main()--后文会讲 caller.run(); } catch (RuntimeException ex) { closeServerSocket(); throw ex; } }
上面是个大概流程,下面会依据源码一步步解释。设置DDMS
可用以后初始化各类参数,在此以后注册为Zygote
进程注册Socket
,预加载各类资源,但这些都不是重点!同窗们,重点在于startSystemServer(abiList, socketName)
(手敲黑板状)!下面简单贴下registerZygoteSocket(socketName)
和preload()
源码,不感兴趣的同窗可直接略过下面两段代码。socket
ZygoteInit#registerZygoteSocket()函数
private static void registerZygoteSocket(String socketName) { if (sServerSocket == null) { int fileDesc; final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; ... FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); // 不是使用IP和端口、而是使用fd建立socket sServerSocket = new LocalServerSocket(fd); ... } }
ZygoteInit#registerZygoteSocket()oop
static void preload() { preloadClasses(); // 加载所需的各类class文件 preloadResources(); // 加载资源文件 preloadOpenGL(); // 初始化OpenGL preloadSharedLibraries(); // 加载系统Libraries preloadTextResources(); //加载文字资源 WebViewFactory.prepareWebViewInZygote(); // 初始化WebView }
跟进startSystemServer()
ui
private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_BLOCK_SUSPEND, OsConstants.CAP_KILL, ... ); /* 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,1021,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "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) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; }
前面一大段都在构造参数,直接进到try
中的代码块。首先根据args
数组构造了一个ZygoteConnection.Arguments
,而后根据parsedArgs
对象的各类参数调用Zygote#forkSyatemServer()
方法fork
出第一个子进程,也就是SystemServer
进程。最后经过执行handleSystemServerProcess
反射调用SystemServer#main()
。能够看到,这段代码最主要的做用就是fork
出SystemServer
进程。这里还看不出反射调用的具体细节,下文会一一分析。spa
首先看下构造ZygoteConnection.Arguments
对象时,具体都作了哪些工做,尤为关注Zygote#forkSystemServer()
中几个参数的值。
源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection$Arguments.java
Arguments(String args[]) throws IllegalArgumentException { parseArgs(args); } private void parseArgs(String args[]) throws IllegalArgumentException { int curArg = 0; boolean seenRuntimeArgs = false; 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; uid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); } else if (arg.startsWith("--setgid=")) { if (gidSpecified) { gidSpecified = true; gid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); } else if (arg.startsWith("--target-sdk-version=")) { targetSdkVersionSpecified = true; targetSdkVersion = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); } ... else if (arg.equals("--runtime-args")) { seenRuntimeArgs = true; } else if (arg.startsWith("--capabilities=")) { 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("--setgroups=")) { 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.startsWith("--nice-name=")) { niceName = arg.substring(arg.indexOf('=') + 1); } else { break; } } // 保存没有被解析的参数 remainingArgs = new String[args.length - curArg]; System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length); }
对比传入的args
数组,能够发现:parsedArgs.uid=1000
、parsedArgs.gid=1000
、parsedArgs.gids={"1001","1002",..."3007"}
、parsedArgs.gid=1000
、parsedArgs.niceName=system_server
、parsedArgs.seenRuntimeArgs=true
。若是中途结束,保存未解析的参数至remainingArgs
数组。
得到Arguments
对象以后,就开始请求建立SystemServer
进程。
源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
ZygoteInit#handleSystemServerProcess()
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket(); if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } ... // 默认为null if (parsedArgs.invokeWith != null) { ... } else { ... RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } /* should never reach here */ }
由Zygote
建立的子进程默认拥有Zygote
进程的Socket
对象,而子进程又用不上,因此先调用closeServerSocket()
关闭它。上一段参数解析时写道:parsedArgs.niceName=system_server
,在这里调用Process.setArgV0()
设置进程名为:system_server
。因为parsedArgs.invokeWith
属性默认为null
,最后调用RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl)
来进一步启动SystemServer
,这里的参数parsedArgs.remainingArgs
就是上文中保存没有被解析对象的数组。
源码位置:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
RuntimeInit#zygoteInit()
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { // 重定向Log输出 redirectLogStreams(); //初始化运行环境 commonInit(); //启动Binder线程池 nativeZygoteInit(); //调用程序入口函数 applicationInit(targetSdkVersion, argv, classLoader); }
RuntimeInit#applicationInit()
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { // 初始化虚拟机环境 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { return; } // Remaining arguments are passed to the start class's static main invokeStaticMain(args.startClass, args.startArgs, classLoader); }
RuntimeInit#invokeStaticMain()
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; try { cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { throw new RuntimeException("Missing class when invoking static main " + className, ex); } Method m; try { // 获取main方法 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); } throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
这里传入的className
就是com.android.server.SystemServer
,而后获取main
方法,接着判断修饰符,必须是static
并且必须是public
类型。最有意思的莫过于作完这一切以后,抛出了个MethodAndArgsCaller
异常。辛苦辛苦各类初始化,各类变着法儿的调用,最后你竟然给我抛个异常!!先别急,这个异常在Zygote#main()
方法中捕获。这么作的做用是清除应用程序进程建立过程的调用栈。
public static void main(String argv[]) { try { ... startSystemServer(abiList, socketName); ... } catch (MethodAndArgsCaller caller) { caller.run(); } }
跟进MethodAndArgsCaller#run()
,感受要出大事情!!
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); } }
我就说要出大事情!我就说要出大事情!!我就说要出大事情!!!能够看到在这里经过反射调用了com.android.server.SystemServer#main(String[] args)
。至此,Zygote
进程for
出SystemServer
进程,并成功调用SystemServer#main()
。
如今SystemServer
进程也建立了,main
方法也调用了。Zygote
进程的使命就此完结了吗?上文咱们说道:全部的应用进程和SystemServer
进程都是由Zygote
进程fork
而来。如今有关SystemServer
进程的已经告一段落,那有关应用进程呢?
让咱们再次回到ZygoteInit#main()
public static void main(String argv[]) { ... startSystemServer(abiList, socketName); runSelectLoop(abiList); closeServerSocket(); }
main
方法中前面全部的代码好像都和应用进程没有关系,最后一行又是关闭socket
,看来和应用进程相关的设置都在runSelectLoop()
中,跟进。
ZygoteInit#runSelectLoop()、ZygoteInit#acceptCommandPeer()
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); int loopCount = GC_LOOP_COUNT; while (true) { int index; if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount--; } try { fdArray = fds.toArray(fdArray); index = selectReadable(fdArray); } catch (IOException ex) { throw new RuntimeException("Error in select()", ex); } if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) { ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDescriptor()); } else { boolean done; done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } } private static ZygoteConnection acceptCommandPeer(String abiList) { try { return new ZygoteConnection(sServerSocket.accept(), abiList); } catch (IOException ex) { throw new RuntimeException("IOException during accept()", ex); } }
这里有个死循环,一直监听socket
,而后调用ZygoteConnection#runOnce()
,从函数名runOnce
上感受真相就要呼之欲出了,跟进。
源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
ZygoteConnection#runOnce()
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[]; args = readArgumentList(); parsedArgs = new Arguments(args); try { ... pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir); } catch (ErrnoException ex) { logAndPrintError(newStderr, "Exception creating pipe", ex); } catch (IllegalArgumentException ex) { logAndPrintError(newStderr, "Invalid zygote arguments", ex); } catch (ZygoteSecurityException ex) { logAndPrintError(newStderr, "Zygote security policy prevents request: ", ex); } try { if (pid == 0) { // in child IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); // should never get here, the child is expected to either // throw ZygoteInit.MethodAndArgsCaller or exec(). return true; } else { // in parent...pid of < 0 means failure IoUtils.closeQuietly(childPipeFd); childPipeFd = null; return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }
和启动SystemServer
进程相似。这里调用Zygote#forkAndSpecialize()
建立应用进程,而参数parsedArgs
是经过socket
一行行读出来的。详见ZygoteConnection#readArgumentList()
private String[] readArgumentList() throws IOException { int argc; try { String s = mSocketReader.readLine(); if (s == null) { return null; } argc = Integer.parseInt(s); } catch (NumberFormatException ex) { throw new IOException("invalid wire format"); } if (argc > MAX_ZYGOTE_ARGC) { throw new IOException("max arg count exceeded"); } String[] result = new String[argc]; for (int i = 0; i < argc; i++) { result[i] = mSocketReader.readLine(); if (result[i] == null) { // We got an unexpected EOF. throw new IOException("truncated request"); } } return result; }
由于尚未看发送Socket
消息的源码,这里斗胆猜想:应该是uid、gid、niceName等参数。
经过Socket
读取完各类参数以后,调用ZygoteConnection#handleChildProc()
,建立完应用程序进程以后就该调用应用程序的入口方法了。跟进。
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { // 关闭从Zygote进程复制过来的Socket链接 closeSocket(); ZygoteInit.closeServerSocket(); if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } ... RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */); }
最后调用RuntimeInit#zygoteInit()
,后面的就和SystemServer
启动流程相似。感兴趣的同窗自行查看。
Zygote
启动流程:初始化DDMS
注册Zygote
进程的Socket
加载class
、resource
、OpenGL
、WebView
等各类资源
fork
出SystemServer
进程
启动SystemServer
进程
调用runSelectLoop()
一直监听Socket
信息
收到建立应用程序Socket
消息,调用ZygoteConnection#runOnce()
。在runOnce()
中调用Zygote#forkAndSpecialize()
建立应用进程
启动应用进程