Java 世界的盘古和女娲 —— Zygote
仔细看看下面这张 Android 体系图,找一下 上图来自 Gityuan 博客 。 纵观整个 Android 体系结构,底层内核空间以 Linux Kernel 为核心,上层用户空间以 C++/Java 组成的 Framework 层组成,通过系统调用来连接用户空间和内核空间。而用户空间又分为 Native 世界和 Java 世界,通过 JNI 技术进行连接。Native 世界的
public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); // Mark zygote start. This ensures that thread creation will throw // an error. ZygoteHooks.startZygoteNoThreadCreation(); // Zygote goes into its own process group. // 设置进程组 ID // pid 为 0 表示设置当前进程的进程组 ID // gid 为 0 表示使用当前进程的 PID 作为进程组 ID try { Os.setpgid(0,0); } catch (ErrnoException ex) { throw new RuntimeException("Failed to setpgid(0,0)",ex); } final Runnable caller; try { ...... RuntimeInit.enableDdms(); // 启用 DDMS boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; for (int i = 1; i < argv.length; i++) { // 参数解析 if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if ("--enable-lazy-preload".equals(argv[i])) { enableLazyPreload = 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]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } // 1. 注册服务端 socket,这里的 IPC 不是 Binder 通信 zygoteServer.registerServerSocketFromEnv(socketName); // In some configurations,we avoid preloading resources and classes eagerly. // In such cases,we will preload things prior to our first fork. if (!enableLazyPreload) { bootTimingsTraceLog.traceBegin("ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis()); preload(bootTimingsTraceLog); // 2. 预加载操作 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis()); bootTimingsTraceLog.traceEnd(); // ZygotePreload } else { Zygote.resetNicePriority(); // 设置线程优先级为 NORM_PRIORITY (5) } // Do an initial gc to clean up after startup gcAndFinalize(); // 3. 强制进行一次垃圾收集 Zygote.nativeSecurityInit(); // Zygote process unmounts root storage spaces. Zygote.nativeUnmountStorageOnInit(); ZygoteHooks.stopZygoteNoThreadCreation(); if (startSystemServer) { // 4. 启动SystemServer 进程 Runnable r = forkSystemServer(abiList,socketName,zygoteServer); // {@code r == null} in the parent (zygote) process,and {@code r != null} in the // child (system_server) process. if (r != null) { r.run(); // 由 RuntimeInit.java 中的 MethodAndArgsCaller 反射调用SystemServer 的 main() 方法 return; } } Log.i(TAG,"Accepting command socket connections"); // The select loop returns early in the child process after a fork and // loops forever in the zygote. // 5. 循环等待处理客户端请求 caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG,"System zygote died with exception",ex); throw ex; } finally { zygoteServer.closeServerSocket(); // 关闭并释放 socket 连接 } // We're in the child process and have exited the select loop. Proceed to execute the // command. if (caller != null) { caller.run(); } } 省去部分不是那么重要的代码,
上面基本上就是 Zygote 的全部使命了,下面按照这个流程来详细分析。 registerServerSocketFromEnv> ZygoteServer.java void registerServerSocketFromEnv(String socketName) { if (mServerSocket == null) { int fileDesc; final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { // 从环境变量中获取 socket 的 fd String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException(fullSocketName + " unset or invalid",ex); } try { FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); // 设置文件描述符 mServerSocket = new LocalServerSocket(fd); // 创建服务端 socket mCloseSocketFd = true; } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'",ex); } } } 首先从环境变量中获取 socket 的文件描述符 fd,然后根据 fd 创建服务端 preload()> ZygoteInit.java static void preload(TimingsTraceLog bootTimingsTraceLog) { ...... preloadClasses(); // 预加载并初始化 /system/etc/preloaded-classes 中的类 ...... preloadResources(); // 预加载系统资源 ...... nativePreloadAppProcessHALs(); // HAL? ...... preloadOpenGL(); // 预加载 OpenGL ...... preloadSharedLibraries(); // 预加载 共享库,包括 android、compiler_rt、jnigraphics 这三个库 preloadTextResources(); // 预加载文字资源 // Ask the WebViewFactory to do any initialization that must run in the zygote process,// for memory sharing purposes. // WebViewFactory 中一些必须在 zygote 进程中进行的初始化工作,用于共享内存 WebViewFactory.prepareWebViewInZygote(); warmUpJcaProviders(); sPreloadComplete = true; }
preloadClasses()> ZygoteInit.java private static void preloadClasses() { ...... InputStream is; try { // /system/etc/preloaded-classes is = new FileInputStream(PRELOADED_CLASSES); } catch (FileNotFoundException e) { Log.e(TAG,"Couldn't find " + PRELOADED_CLASSES + "."); return; } try { BufferedReader br = new BufferedReader(new InputStreamReader(is),256); int count = 0; String line; while ((line = br.readLine()) != null) { // Skip comments and blank lines. line = line.trim(); if (line.startsWith("#") || line.equals("")) { continue; } try { // Load and explicitly initialize the given class. Use // Class.forName(String,boolean,ClassLoader) to avoid repeated stack lookups // (to derive the caller's class-loader). Use true to force initialization,and // null for the boot classpath class-loader (could as well cache the // class-loader of this class in a variable). Class.forName(line,true,null); count++; } catch (ClassNotFoundException e) { Log.w(TAG,"Class not found for preloading: " + line); } catch (UnsatisfiedLinkError e) { Log.w(TAG,"Problem preloading " + line + ": " + e); } catch (Throwable t) { ...... } } } catch (IOException e) { Log.e(TAG,"Error reading " + PRELOADED_CLASSES + ".",e); } finally { IoUtils.closeQuietly(is); ...... } } 只保留了核心逻辑代码。读取 preloadResources()> ZygoteInit.java private static void preloadResources() { final VMRuntime runtime = VMRuntime.getRuntime(); try { mResources = Resources.getSystem(); mResources.startPreloading(); if (PRELOAD_RESOURCES) { TypedArray ar = mResources.obtainTypedArray( com.android.internal.R.array.preloaded_drawables); int N = preloadDrawables(ar); ar.recycle(); ...... ar = mResources.obtainTypedArray( com.android.internal.R.array.preloaded_color_state_lists); N = preloadColorStateLists(ar); ar.recycle(); if (mResources.getBoolean( com.android.internal.R.bool.config_freeformWindowManagement)) { ar = mResources.obtainTypedArray( com.android.internal.R.array.preloaded_freeform_multi_window_drawables); N = preloadDrawables(ar); ar.recycle(); } } mResources.finishPreloading(); } catch (RuntimeException e) { Log.w(TAG,"Failure preloading resources",e); } } 从源码中可知,主要加载的资源有:
preloadSharedLibraries()> ZygoteInit.java private static void preloadSharedLibraries() { Log.i(TAG,"Preloading shared libraries..."); System.loadLibrary("android"); System.loadLibrary("compiler_rt"); System.loadLibrary("jnigraphics"); } 预加载了三个共享库, gcAndFinalize()> ZygoteInit.java static void gcAndFinalize() { final VMRuntime runtime = VMRuntime.getRuntime(); /* runFinalizationSync() lets finalizers be called in Zygote,* which doesn't have a HeapWorker thread. */ System.gc(); runtime.runFinalizationSync(); System.gc(); } 在 forkSystemServer()主动调用 GC 之后,Zygote 就要去做它的大事 —— fork SystemServer 进程了。 > ZygoteInit.java private static Runnable forkSystemServer(String abiList,String socketName,...... /* 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,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010","--capabilities=" + capabilities + "," + capabilities,"--nice-name=system_server",// 进程名 "--runtime-args","--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,"com.android.server.SystemServer",// 加载类名 }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); boolean profileSystemServer = SystemProperties.getBoolean( "dalvik.vm.profilesystemserver",false); if (profileSystemServer) { parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER; } /* Request to fork the system server process * fork system_server 进程 */ pid = Zygote.forkSystemServer( parsedArgs.uid,parsedArgs.gid,parsedArgs.gids,parsedArgs.runtimeFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ // pid == 0 表示子进程,从这里开始进入 system_server 进程 if (pid == 0) { if (hasSecondZygote(abiList)) { // 如果有第二个 Zygote waitForSecondaryZygote(socketName); } zygoteServer.closeServerSocket(); // 关闭并释放从 Zygote copy 过来的 socket return handleSystemServerProcess(parsedArgs); // 完成新创建的 system_server 进程的剩余工作 } /** * 注意 fork() 函数式一次执行,两次返回(两个进程对同一程序的两次执行)。 * pid > 0 说明还是父进程。pid = 0 说明进入了子进程 * 所以这里的 return null 依旧会执行 */ return null; } 从上面的启动参数可以看到, > Zygote.java public static int forkSystemServer(int uid,int gid,int[] gids,int runtimeFlags,int[][] rlimits,long permittedCapabilities,long effectiveCapabilities) { VM_HOOKS.preFork(); // Resets nice priority for zygote process. resetNicePriority(); int pid = nativeForkSystemServer( uid,gid,gids,runtimeFlags,rlimits,permittedCapabilities,effectiveCapabilities); // Enable tracing as soon as we enter the system_server. if (pid == 0) { Trace.setTracingEnabled(true,runtimeFlags); } VM_HOOKS.postForkCommon(); return pid; } native private static int nativeForkSystemServer(int uid,long effectiveCapabilities); 最后的 if(pid == 0){ ...... return handleSystemServerProcess(parsedArgs); } return null; 按正常逻辑思维,这两处 if (startSystemServer) { Runnable r = forkSystemServer(abiList,zygoteServer); // {@code r == null} in the parent (zygote) process,and {@code r != null} in the // child (system_server) process. // r == null 说明是在 zygote 进程 // r != null 说明是在 system_server 进程 if (r != null) { r.run(); return; } } // 循环等待处理客户端请求 caller = zygoteServer.runSelectLoop(abiList); 子进程 system_server 返回的是一个 Runnable,执行 下面就来分析 handleSystemServerProcess到这里其实已经脱离 Zygote 的范畴了,本准备放在下一篇 > ZygoteInit.java private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) { // set umask to 0077 so new files and directories will default to owner-only permissions. // umask一般是用在你初始创建一个目录或者文件的时候赋予他们的权限 Os.umask(S_IRWXG | S_IRWXO); // 设置当前进程名为 "system_server" if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH"); if (systemServerClasspath != null) { // dex 优化操作 performSystemServerDexOpt(systemServerClasspath); // Capturing profiles is only supported for debug or eng builds since selinux normally // prevents it. boolean profileSystemServer = SystemProperties.getBoolean( "dalvik.vm.profilesystemserver",false); if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) { try { prepareSystemServerProfile(systemServerClasspath); } catch (Exception e) { Log.wtf(TAG,"Failed to set up system server profile",e); } } } if (parsedArgs.invokeWith != null) { // invokeWith 一般为空 String[] args = parsedArgs.remainingArgs; // If we have a non-null system server class path,we'll have to duplicate the // existing arguments and append the classpath to it. ART will handle the classpath // correctly when we exec a new process. if (systemServerClasspath != null) { String[] amendedArgs = new String[args.length + 2]; amendedArgs[0] = "-cp"; amendedArgs[1] = systemServerClasspath; System.arraycopy(args,amendedArgs,2,args.length); args = amendedArgs; } WrapperInit.execApplication(parsedArgs.invokeWith,parsedArgs.niceName,parsedArgs.targetSdkVersion,VMRuntime.getCurrentInstructionSet(),args); throw new IllegalStateException("Unexpected return from WrapperInit.execApplication"); } else { ClassLoader cl = null; if (systemServerClasspath != null) { // 创建类加载器,并赋给当前线程 cl = createPathClassLoader(systemServerClasspath,parsedArgs.targetSdkVersion); Thread.currentThread().setContextClassLoader(cl); } /* * Pass the remaining arguments to SystemServer. */ return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs,cl); } /* should never reach here */ } 设置进程名为 public static final Runnable zygoteInit(int targetSdkVersion,String[] argv,ClassLoader classLoader) { ...... // Redirect System.out and System.err to the Android log. // 重定向 System.out 和 System.err 到 Android log RuntimeInit.redirectLogStreams(); RuntimeInit.commonInit(); // 一些初始化工作 ZygoteInit.nativeZygoteInit(); // native 层初始化 return RuntimeInit.applicationInit(targetSdkVersion,argv,classLoader); // 调用入口函数 } 重定向 Log,进行一些初始化工作。这部分不细说了,点击文章开头给出的源码链接,大部分都做了注释。最后调用 > RuntimeInit.java protected static Runnable applicationInit(int targetSdkVersion,ClassLoader classLoader) { ...... final Arguments args = new Arguments(argv); // 解析参数 ...... // 寻找 startClass 的 main() 方法。这里的 startClass 是 com.android.server.SystemServer return findStaticMain(args.startClass,args.startArgs,classLoader); } 这里的 protected static Runnable findStaticMain(String className,ClassLoader classLoader) { Class<?> cl; try { cl = Class.forName(className,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); } /* * 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. * 返回一个 Runnable,在 Zygote 的 main() 方法中执行器 run() 方法 * 之前的版本是抛出一个异常,在 main() 方法中捕获 */ return new MethodAndArgsCaller(m,argv); } 找到 main() 方法并构建一个 Runnable 对象 再来看看 static class MethodAndArgsCaller implements Runnable { /** method to call */ private final Method mMethod; /** argument array */ private final String[] mArgs; public MethodAndArgsCaller(Method method,String[] args) { mMethod = method; mArgs = args; } 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); } } } 就一件事,执行参数中的 其实在老版本的 Android 源码中,并不是通过这种方法执行
看到这里, runSelectLoop> ZygoteServer.java Runnable runSelectLoop(String abiList) { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); // mServerSocket 是之前在 Zygote 中创建的 fds.add(mServerSocket.getFileDescriptor()); peers.add(null); while (true) { StructPollfd[] pollFds = new StructPollfd[fds.size()]; for (int i = 0; i < pollFds.length; ++i) { pollFds[i] = new StructPollfd(); pollFds[i].fd = fds.get(i); pollFds[i].events = (short) POLLIN; } try { // 有事件来时往下执行,没有时就阻塞 Os.poll(pollFds,-1); } catch (ErrnoException ex) { throw new RuntimeException("poll failed",ex); } for (int i = pollFds.length - 1; i >= 0; --i) { if ((pollFds[i].revents & POLLIN) == 0) { continue; } if (i == 0) { // 有新客户端连接 ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { // 处理客户端请求 try { ZygoteConnection connection = peers.get(i); final Runnable command = connection.processOneCommand(this); ...... } catch (Exception e) { ...... } } } }
...... pid = Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.mountExternal,parsedArgs.seInfo,fdsToClose,fdsToIgnore,parsedArgs.startChildZygote,parsedArgs.instructionSet,parsedArgs.appDataDir); try { if (pid == 0) { // in child 进入子进程 zygoteServer.setForkChild(); zygoteServer.closeServerSocket(); IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; return handleChildProc(parsedArgs,descriptors,childPipeFd,parsedArgs.startChildZygote); } else { // In the parent. A pid < 0 indicates a failure and will be handled in // handleParentProc. IoUtils.closeQuietly(childPipeFd); childPipeFd = null; handleParentProc(pid,serverPipeFd); return null; } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } 乍一看是不是感觉有点眼熟?没错,这一块的逻辑和 还有一个问题,上面只分析了 Zygote 接收到客户端请求并响应,那么这个客户端可能是谁呢?具体又是如何与 Zygote 通信的呢?关于这个问题,后续文章中肯定会写到,关注我的 Github 仓库 android_9.0.0_r45,所有文章都会第一时间同步过去。 总结来一张时序图总结全文 : 最后想说说如何阅读 AOSP 源码和开源项目源码。我的看法是,不要上来就拼命死磕,一行一行的非要全部看懂。首先要理清脉络,能大致的理出来一个时序图,然后再分层细读。这个细读的过程中碰到不懂的知识点就得自己去挖掘,比如文中遇到的 下篇文章会具体说说
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |