Android 5.1 Lollipop的Zygote分析——下篇
上一篇结尾的时候,说过AppRuntime的start()最后会加载Java层次的ZygoteInit类(com.android.internal.os.ZygoteInit),并调用其main函数。
ZygoteInit要做一些和Android平台紧密相关的重要动作,比如创建LocalServerSocket对象、预加载一些类以及资源、启动“Android系统服务”.
ZygoteInit类源码位置:Android源码/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public static void main(String argv[]) { try { // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote";//----------------------------------- ................................................. registerZygoteSocket(socketName);//-----------------------注册zygote套接字 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload();//------------------------------------------------预加载资源 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); ................................................. if (startSystemServer) {//-------------------------------- 启动 system server 服务 startSystemServer(abiList, socketName); } Log.i(TAG, "Accepting command socket connections"); runSelectLoop(abiList);//------------------------------------ closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } } |
registerZygoteSocket
其中registerZygoteSocket函数代码如下图所示
代码中 ANDROID_SOCKET_PREFIX 定义如下:
1 |
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_"; |
那么fullSocketName就是ANDROID_SOCKET_zygote了。要想知道这个环境变量,是怎么来的,那就要先分析init进程了,这不是我们的重点,等后面分析init进程的时候,在详细讨论这个变量的由来。
这里先简单说一下吧。在前面提到的关于zygote的rc配置文件,例如init.zygote32.rc中,有这么个option内容:
1 |
socket zygote stream 660 root system |
说明zygote进程需要一个名为“zygote”的“流型(stream)”socket,当init进程真的启动zygote服务时,会走到service_start(),该函数会检查到zygote服务,需要一个“流型(stream)”的socket,那么便会在/dev/socket中为其创建一个名为zygote的流类型socket,并把新建的socket的文件描述符记录在以“ANDROID_SOCKET_zygote”的环境变量中。
那么ZygoteInit类中main函数下面的代码就清楚了其含义了:
1 2 |
String env = System.getenv(ANDROID_SOCKET_ENV); fileDesc = Integer.parseInt(env); |
从环境变量的字符串中解析出文件描述符,然后创建LocalServerSocket对象,并将其记录在静态变量sServerSocket中,以后zygote进程会循环监听这个socket,一旦accept到连接请求,就创建命令连接(Command Connection)。监听动作的细节是在runSelectLoop()中。
预先加载类和资源
预先加载类
注册完socket接口,ZygoteInit会预加载一些类,这些类记录在Android源码/frameworks/base/preloaded-classes文本文件里:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Classes which are preloaded by com.android.internal.os.ZygoteInit. # Automatically generated by frameworks/base/tools/preload/WritePreloadedClassFile.java. # MIN_LOAD_TIME_MICROS=1250 # MIN_PROCESSES=10 ........................................ [Landroid.accounts.Account; [Landroid.animation.Animator; [Landroid.animation.Keyframe$FloatKeyframe; [Landroid.animation.Keyframe$IntKeyframe; [Landroid.animation.PropertyValuesHolder; [Landroid.app.FragmentState; [Landroid.app.LoaderManagerImpl; ........................................ |
这个文件开头已经说的很清楚了,预先加载的这些类,每个加载时间都至少是1250微秒。Android 5.1中预先加载的类大约有3000个,可想而已Android启动的时候,花在这上面的时间可不少呢。preload函数中会调研preloadClasses()的函数预先加载这些类。
预先加载资源
preload函数中还会利用preloadResources()函数预先加载一些资源,这些资源记录在Android源码/frameworks/base/core/res/res/values/arrays.xml中。
基本上有两大类资源:
1)一类和图片有关(preloaed_drawables)
2)另一类和颜色有关(preloaded_color_state_lists)
预先加载的其他资源
preload函数还要调用下面两个函数还要预先加载opengl和一些so库。
1 2 3 4 5 6 7 8 9 10 11 12 |
private static void preloadSharedLibraries() { Log.i(TAG, "Preloading shared libraries..."); System.loadLibrary("android"); System.loadLibrary("compiler_rt"); System.loadLibrary("jnigraphics"); } private static void preloadOpenGL() { if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) { EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); } } |
启动system server服务
ZygoteInit的main()函数会调用startSystemServer()来启动system server,这是Android上层系统最重要的服务了。其大体做法是先fork一个子进程,然后在子进程中做一些初始化动作,继而执行SystemServer类的main()静态函数。需要注意的是,startSystemServer()并不是在函数体内直接调用Java类的main()函数的,而是通过抛异常的方式,在startSystemServer()之外加以处理的。
startSystemServer函数部分代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
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,1021,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); // fork出系统服务对应的进程 pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } // 对新fork出的系统进程,执行handleSystemServerProcess() if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; } |
Zygote.forkSystemServer
android源码/frameworks/base/core/java/com/android/internal/os/Zygote.java
1 2 3 4 5 6 7 8 |
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { VM_HOOKS.preFork(); int pid = nativeForkSystemServer( uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities); VM_HOOKS.postForkCommon(); return pid; } |
其中参数可以从下面获取:
1 2 3 4 5 6 7 8 9 10 |
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, "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; |
nativeForkSystemServer()是个native成员函数,其对应的C++层代码位置:Android源码/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
static jint com_android_internal_os_Zygote_nativeForkSystemServer( JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids, jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities, jlong effectiveCapabilities) { pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, permittedCapabilities, effectiveCapabilities, MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL, NULL, NULL); if (pid > 0) { // The zygote process checks whether the child process has died or not. ALOGI("System server process %d has been created", pid); gSystemServerPid = 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. int status; if (waitpid(pid, &status, WNOHANG) == pid) { ALOGE("System server process %d has died. Restarting Zygote!", pid); RuntimeAbort(env); } } return pid; } |
forkAndSpecializeCommon()内部其实会调用fork(),而后设置gid、uid等信息
handleSystemServerProcess
startSystemServer()会在新fork出的子进程中调用handleSystemServerProgress(),让这个新进程成为真正的系统进程(SystemServer进程)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
/** * Finish remaining work for the newly forked system server process. */ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket();//------------------因为子进程是system server 不是zygote,所以要关闭zygote socket // set umask to 0077 so new files and directories will default to owner-only permissions. Os.umask(S_IRWXG | S_IRWXO); if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName);//----------------niceName 是 system_server } final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH"); if (systemServerClasspath != null) { performSystemServerDexOpt(systemServerClasspath); } if (parsedArgs.invokeWith != null) { 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(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length); } WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, null, args); } else { ClassLoader cl = null; if (systemServerClasspath != null) { cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader()); Thread.currentThread().setContextClassLoader(cl); } /* * Pass the remaining arguments to SystemServer. */ // 此时的remainingArgs就是”com.android.server.SystemServer” RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } /* should never reach here */ } |
因为当前已经不是运行在zygote进程里了,所以zygote里的那个监听socket就应该关闭了.在handleSystemServerProcess()函数里,parsedArgs.niceName就是“system_server”,而且因为parsedArgs.invokeWith没有指定,所以其值为null,于是程序会走到RuntimeInit.zygoteInit().
Android源码/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
1 2 3 4 5 6 7 8 9 10 11 |
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); redirectLogStreams();//-------------在新fork出的系统进程里,需要重新定向系统输出流 commonInit(); nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader); } |
上面调用的nativeZygoteInit()是个JNI函数,在AndroidRuntime.cpp文件中可以看到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* * JNI registration. */ static JNINativeMethod gMethods[] = { { "nativeFinishInit", "()V", (void*) com_android_internal_os_RuntimeInit_nativeFinishInit }, { "nativeZygoteInit", "()V", (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit }, { "nativeSetExitWithoutCleanup", "(Z)V", (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup }, }; static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); } |
gCurRuntime是C++层的AndroidRuntime类的静态变量。在AndroidRuntime构造之时,gCurRuntime = this
其中onZygoteInit是一个虚函数,是有AndroidRuntime的子类AppRuntime负责实现的。
Android源码/framework/base/cmds/app_process/App_main.cpp
1 2 3 4 5 6 7 8 9 |
virtual void onZygoteInit() { // Re-enable tracing now that we're no longer in Zygote. atrace_set_tracing_enabled(true); sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); } |
里面构造了进程的ProcessState全局对象,而且启动了线程池。 这就涉及到了Binder机制的知识了,关于Binder后面再讲。
也就是说system server进程内部会开启一个线程池。
在来看applicationInit()函数的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { nativeSetExitWithoutCleanup(true); 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, classLoader); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
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 { m = cl.getMethod("main", new Class[] { String[].class });//-----------------注意看这里的 main } 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); } |
可见在invokeStaticMain函数中最后抛出了异常。这相当于一个“特殊的goto语句”!上面的cl = Class.forName函数,其实加载的就是SystemServer类。这个类名是从前文的parsedArgs.remainingArgs得来的,其值就是“com.android.server.SystemServer”。此处抛出的异常,会被本进程的catch语句接住,在那里才会执行SystemServer类的main()函数
如下图所示,新fork出的SystemServer子进程直接跳过了中间那句runSelectLoop(),去执行caller.run()去了,也就是说这个run函数是在子进程中执行的。
父进程Zygote在fork动作后,会退出startSystemServer()函数,并走到runSelectLoop(),从而进入一种循环监听状态,每当Activity Manager Service向它发出“启动新应用进程”的命令时,它又会fork一个子进程,并在子进程里抛出一个异常,这样子进程还是会跳转到catch一句。
现在看以下 SystemServer类的main函数:
frameworks/base/services/java/com/android/server/SystemServer.java
1 2 3 4 5 6 |
/** * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); } |
可见创建了SystemServer对象,并且执行其run函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
private void run() { // 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. if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } // Here we go! Slog.i(TAG, "Entered the Android system server!"); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); // In case the runtime switched since last boot (such as when // the old runtime was removed in an OTA), set the system // property so that it is in sync. We can't do this in // libnativehelper's JniInvocation::Init code where we already // had to fallback to a different runtime because it is // running as root and we need to be the system user to set // the property. http://b/11463182 SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary()); // Enable the sampling profiler. if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); mProfilerSnapshotTimer = new Timer(); mProfilerSnapshotTimer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } // Mmmmmm... more memory! 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); // Some devices rely on runtime fingerprint generation, so make sure // we've defined it before booting further. Build.ensureFingerprintProperty(); // Within the system server, it is an error to access Environment paths without // explicitly specifying a user. Environment.setUserRequired(true); // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); // Initialize native services. System.loadLibrary("android_servers"); nativeInit(); // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context. createSystemContext(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); } // Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } |
可见会初始化 native services.
1 2 |
System.loadLibrary("android_servers"); nativeInit(); |
监听zygote socket
ZygoteInit的main()函数在调用完startSystemServer()之后,zygote进程会进一步走到runSelectLoop()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
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());//------------------------sServerSocket就是zygote socket文件描述符 peers.add(null); int loopCount = GC_LOOP_COUNT; while (true) { int index; /* * Call gc() before we block in select(). * It's work that has to be done anyway, and it's better * to avoid making every child do it. It will also * madvise() any free memory as a side-effect. * * Don't call it every time, because walking the entire * heap is a lot of overhead to free a few hundred bytes. */ if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount--; } try { fdArray = fds.toArray(fdArray);//-----------------------------fdArry中就包含了zygote socket文件描述符了 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) {//-----------------------------------------对应的zygote socket有数据可读 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); } } } } |
在一个while循环中,不断调用selectReadable()。该函数是个native函数,对应C++层的com_android_internal_os_ZygoteInit_selectReadable()。
Android源码/frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp
1 2 3 4 5 6 7 |
static JNINativeMethod gMethods[] = {................................................................. { "selectReadable", "([Ljava/io/FileDescriptor;)I", (void *) com_android_internal_os_ZygoteInit_selectReadable }, { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;", (void *) com_android_internal_os_ZygoteInit_createFileDescriptor } }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
static jint com_android_internal_os_ZygoteInit_selectReadable (JNIEnv *env, jobject clazz, jobjectArray fds) { . . . . . . int err; do { err = select (nfds, &fdset, NULL, NULL, NULL); } while (err < 0 && errno == EINTR); . . . . . . for (jsize i = 0; i < length; i++) { jobject fdObj = env->GetObjectArrayElement(fds, i); . . . . . . int fd = jniGetFDFromFileDescriptor(env, fdObj); . . . . . . if (FD_ISSET(fd, &fdset)) { return (jint)i; } } return -1; } |
主要就是调用select()而已。在Linux的socket编程中,select()负责监视若干文件描述符的变化情况,我们常见的变化情况有:读、写、异常等等。
在zygote中,err = select (nfds, &fdset, NULL, NULL, NULL);一句的最后三个参数都为NULL,表示该select()操作只打算监视文件描述符的“读变化”,而且如果没有可读的文件,select()就维持阻塞状态。
在被监视的文件描述符数组(fds)中,第一个文件描述符对应着“zygote接收其他进程连接申请的那个socket(及sServerSocket)”,一旦它发生了变化,我们就尝试建立一个ZygoteConnection。
新创建的ZygoteConnection会被再次写入文件描述符数组(fds):
1 |
fds.add(newPeer.getFileDescriptor()); |
如果select动作发现文件描述符数组(fds)的其他文件描述符有东西可读了,说明有其他进程通过某个已建立好的ZygoteConnection发来了命令,此时我们需要调用runOnce()。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors; . . . . . . args = readArgumentList();//---------------------------------------------------------------- descriptors = mSocket.getAncillaryFileDescriptors(); . . . . . . int pid = -1; FileDescriptor childPipeFd = null; FileDescriptor serverPipeFd = null; try { parsedArgs = new Arguments(args); . . . . . . pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName); } . . . . . . if (pid == 0) { // in child IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); return true; } else { // in parent...pid of < 0 means failure IoUtils.closeQuietly(childPipeFd); childPipeFd = null; return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } . . . . . . } |
runOnce()中从socket中读取参数数据的动作是由readArgumentList()完成的,该函数的代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
private String[] readArgumentList() throws IOException { int argc; . . . . . . String s = mSocketReader.readLine(); . . . . . . argc = Integer.parseInt(s); . . . . . . 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; } |
AMS会想这个socke写入参数。AMS需要启动一个新进程时,会调用类似下面的句子:
1 2 3 |
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread", app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, null); |
包括ActivityThread类名等重要信息的参数,最终就会通过socket传递给zygote。
runOnce()在读完参数之后,会进一步调用到handleChildProc()。该函数会间接抛出特殊的MethodAndArgsCaller异常,只不过此时抛出的异常携带的类名为ActivityThread,前面我们提到的类名是SystemServer。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { closeSocket();//--------------------------------------------因为不是zygote进程了,所以肯定要先关闭socket了 ZygoteInit.closeServerSocket(); . . . . . . if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } if (parsedArgs.runtimeInit) { if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, pipeFd, parsedArgs.remainingArgs); } else { RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } } else { String className; . . . . . . className = parsedArgs.remainingArgs[0]; . . . . . . String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1]; System.arraycopy(parsedArgs.remainingArgs, 1, mainArgs, 0, mainArgs.length); if (parsedArgs.invokeWith != null) { WrapperInit.execStandalone(parsedArgs.invokeWith, parsedArgs.classpath, className, mainArgs); } else { ClassLoader cloader; if (parsedArgs.classpath != null) { cloader = new PathClassLoader(parsedArgs.classpath, ClassLoader.getSystemClassLoader()); } else { cloader = ClassLoader.getSystemClassLoader(); } try { ZygoteInit.invokeStaticMain(cloader, className, mainArgs);//-----------------------很熟悉吧,忘了的话,往上看 } catch (RuntimeException ex) { logAndPrintError(newStderr, "Error starting.", ex); } } } } |
Zygote进程实际上是利用fork()创建新进程。如果fork()出的新进程是system server,那么其最终执行的就是SystemServer类的main()函数,而如果fork()出的新进程是普通的用户进程的话,那么其最终执行的就是ActivityThread类的main()函数。
原文地址: http://www.iloveandroid.net/2015/09/21/Zygote_2/
Android 5.1 Lollipop的Zygote分析——下篇相关推荐
- Android 5.1 Lollipop的Zygote分析——上篇
整体介绍 因为公司最近的项目,频繁的使用了xposed框架.作为一种Hook技术,xposed框架主要是对Android系统中的app_process程序做了手脚.为了弄清楚xposed框架背后的原理 ...
- Android中init与受精卵Zygote分析,以及添加自己开机启动的系统服务
最近在做云游戏的项目,由于需要购买硬件,系统提供Android源码需要自己编译.所以特地学习一下记录一下Android的启动(我的是AOSP7.1然后+厂商系统补丁) 先上图: 目录 一. 启动流程硬 ...
- Android Zygote分析
1. app_process到zygote zygote本身是一个Native应用程序,和驱动.内核均无关系,zygote是由init进行根据init.rc文件中的配置进行创建的,具体的配置代码如下: ...
- android 的Zygote 分析
jollen 發表於 April 5, 2010 3:14 PM Android 作業系統開機時,會經由 init.rc 來啟動許多外部程式,其中有一個最重要 process 稱為 Zygote.Zy ...
- Android Studio - HPROF文件查看和分析工具
Android Studio - HPROF文件查看和分析工具 Android Studio 翻译的官方文章 原文链接 当你在Android Studio中使用Android Monitor里的Mem ...
- Android系统(244)---Zygote进程的启动流程
Android进程系列第二篇---Zygote进程的启动流程 内容预览.png 概述: 本文(基于Android O源码)主要讲解Zygote进程创建流程,线程容易创建,但进程的相关的东西都被系统很好 ...
- Android 系统(78)---《android framework常用api源码分析》之 app应用安装流程
<android framework常用api源码分析>之 app应用安装流程 <android framework常用api源码分析>android生态在中国已经发展非常庞大 ...
- 转:Android应用开发性能优化完全分析
转自:http://blog.csdn.net/yanbober/article/details/48394201 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜 ...
- Android系统启动流程—— init进程zygote进程SystemServer进程启动流程
原文地址:https://blog.csdn.net/qq_30993595/article/details/82714409 Android系统启动流程 Android系统启动过程往细了说可以分为5 ...
最新文章
- 非本地类型不能定义方法 cannot define new methods on non-local type time.Duration
- Oracle导出空表解决办法
- JavaScript如何声明对象、函数以及对象中的函数(即方法)
- GraphQL入门之graphql-java项目的介绍
- QPushButton hover配置
- react学习(69)--置空操作
- 【计算机组成原理】双端口RAM和多模块存储器
- J2EE实现发送邮件功能
- Web开发技术大会演讲
- 深入阅读Mina源码(3) —— Mina之IOAdapter(二)
- 最新版本elasticsearch本地搭建入门篇
- fork 与 vfork
- html怎么将背景图片旋转,css怎么旋转图片?
- angular7.0+ngx-weui公众号开发,开发及框架搭建(一)
- 半小时一篇文过完C语言基础知识点
- D-009 eMMC电路设计
- matlab 画拉普拉斯变换的零极点
- 笔记本电脑周边双屏显示方案
- Unity插件学习(五) ------ 本地存储Easy Save3
- golang生成UUID通用唯一识别码
热门文章
- static 成员小记
- DRM-内容数据版权加密保护技术学习(上):视频文件打包实现(转)
- leetcode刷题之堆
- Python学习笔记:常用内建模块4:hmac
- iptables防火墙详解
- Python中if __name__ == '__main__':作用
- [云炬创业管理笔记]第四章把握创业机会测试6
- [云炬创业基础笔记]第二章创业者测试1
- [云炬ThinkPython阅读笔记]3.4 增加新函数
- 获得 DataSet中的记录总数