Zygote进程【2】——Zygote的分裂
在Zygote的诞生一文中init进程是如何一步步创建Zygote进程的,也了解了Zygote的进程的作用。Zygote进程的诞生对于整个Java世界可以说有着”开天辟地“的作用,它创建了Java虚拟机,并且繁殖了Java世界的核心服务system_server进程,在完成Java世界的初创工作以后,Zygote并没有死去,它只是暂时的沉睡(socket事件堵塞)在那里,一旦有需要(有客户端请求的到来),它便马上起来工作。本文接下来就将分析一下Zygote是如何监听和处理socket事件的。
首先让我们一起来回忆一下Zygote的main方法:
@frameworks/base/core/java/com/Android/internal/os/ZygoteInit.java
- public static void main(String argv[]) {
- try {
- registerZygoteSocket();//注册zygote用的socket
- ......
- runSelectLoop();//变成守护进程,接收socket信息进行处理
- closeServerSocket();
- } catch (MethodAndArgsCaller caller) {
- caller.run();
- } catch (RuntimeException ex) {
- Log.e(TAG, "Zygote died with exception", ex);
- closeServerSocket();
- throw ex;
- }
- }
main()方法首先在registerZygoteSocket中注册了Zygote的 服务端Socket对象,然后在完成一系列初创工作后调用runSelectLoop进入到死循环中,等待客户端事件的到来。到了这里我们不禁会问,Zygote进程作为服务端,那客户端是谁呢?Zygote接收到客户端连接以后又是如何处理的呢?下面我们就带着这两个问题一起来分析。
客户端请求
@/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
- private final void startProcessLocked(ProcessRecord app,
- String hostingType, String hostingNameStr) {
- ......
- try {
- ......
- // Start the process. It will either succeed and return a result containing
- // the PID of the new process, or else throw a RuntimeException.
- Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
- app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, app.info.seinfo, null);
- .......
- }
@/frameworks/base/core/java/android/os/Process.java
- /**
- * Start a new process.
- *
- * <p>If processes are enabled, a new process is created and the
- * static main() function of a <var>processClass</var> is executed there.
- * The process will continue running after this function returns.
- *
- * <p>If processes are not enabled, a new thread in the caller's
- * process is created and main() of <var>processClass</var> called there.
- *
- * <p>The niceName parameter, if not an empty string, is a custom name to
- * give to the process instead of using processClass. This allows you to
- * make easily identifyable processes even if you are using the same base
- * <var>processClass</var> to start them.
- *
- * @param processClass The class to use as the process's main entry
- * point.
- * @param niceName A more readable name to use for the process.
- * @param uid The user-id under which the process will run.
- * @param gid The group-id under which the process will run.
- * @param gids Additional group-ids associated with the process.
- * @param debugFlags Additional flags.
- * @param targetSdkVersion The target SDK version for the app.
- * @param seInfo null-ok SE Android information for the new process.
- * @param zygoteArgs Additional arguments to supply to the zygote process.
- *
- * @return An object that describes the result of the attempt to start the process.
- * @throws RuntimeException on fatal start failure
- *
- * {@hide}
- */
- public static final ProcessStartResult start(final String processClass,
- final String niceName,
- int uid, int gid, int[] gids,
- int debugFlags, int mountExternal,
- int targetSdkVersion,
- String seInfo,
- String[] zygoteArgs) {
- try {
- return startViaZygote(processClass, niceName, uid, gid, gids,
- debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
- } catch (ZygoteStartFailedEx ex) {
- Log.e(LOG_TAG,
- "Starting VM process through Zygote failed");
- throw new RuntimeException(
- "Starting VM process through Zygote failed", ex);
- }
- }
startViaZygote()方法的实现如下:
- /**
- * Starts a new process via the zygote mechanism.
- *
- * @param processClass Class name whose static main() to run
- * @param niceName 'nice' process name to appear in ps
- * @param uid a POSIX uid that the new process should setuid() to
- * @param gid a POSIX gid that the new process shuold setgid() to
- * @param gids null-ok; a list of supplementary group IDs that the
- * new process should setgroup() to.
- * @param debugFlags Additional flags.
- * @param targetSdkVersion The target SDK version for the app.
- * @param seInfo null-ok SE Android information for the new process.
- * @param extraArgs Additional arguments to supply to the zygote process.
- * @return An object that describes the result of the attempt to start the process.
- * @throws ZygoteStartFailedEx if process start failed for any reason
- */
- private static ProcessStartResult startViaZygote(final String processClass,
- final String niceName,
- final int uid, final int gid,
- final int[] gids,
- int debugFlags, int mountExternal,
- int targetSdkVersion,
- String seInfo,
- String[] extraArgs)
- throws ZygoteStartFailedEx {
- synchronized(Process.class) {
- ArrayList<String> argsForZygote = new ArrayList<String>();
- // --runtime-init, --setuid=, --setgid=,
- // and --setgroups= must go first
- argsForZygote.add("--runtime-init");
- argsForZygote.add("--setuid=" + uid);
- argsForZygote.add("--setgid=" + gid);
- if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
- argsForZygote.add("--enable-jni-logging");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
- argsForZygote.add("--enable-safemode");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
- argsForZygote.add("--enable-debugger");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
- argsForZygote.add("--enable-checkjni");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
- argsForZygote.add("--enable-assert");
- }
- if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
- argsForZygote.add("--mount-external-multiuser");
- } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
- argsForZygote.add("--mount-external-multiuser-all");
- }
- argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
- //TODO optionally enable debuger
- //argsForZygote.add("--enable-debugger");
- // --setgroups is a comma-separated list
- if (gids != null && gids.length > 0) {
- StringBuilder sb = new StringBuilder();
- sb.append("--setgroups=");
- int sz = gids.length;
- for (int i = 0; i < sz; i++) {
- if (i != 0) {
- sb.append(',');
- }
- sb.append(gids[i]);
- }
- argsForZygote.add(sb.toString());
- }
- if (niceName != null) {
- argsForZygote.add("--nice-name=" + niceName);
- }
- if (seInfo != null) {
- argsForZygote.add("--seinfo=" + seInfo);
- }
- argsForZygote.add(processClass);
- if (extraArgs != null) {
- for (String arg : extraArgs) {
- argsForZygote.add(arg);
- }
- }
- return zygoteSendArgsAndGetResult(argsForZygote);
- }
- }
startViaZygote的绝大部分代码都在处理传递到Zygote中的参数,与Zygote通信通过zygoteSendArgsAndGetResult()方法完成:
- /**
- * Sends an argument list to the zygote process, which starts a new child
- * and returns the child's pid. Please note: the present implementation
- * replaces newlines in the argument list with spaces.
- * @param args argument list
- * @return An object that describes the result of the attempt to start the process.
- * @throws ZygoteStartFailedEx if process start failed for any reason
- */
- private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
- throws ZygoteStartFailedEx {
- openZygoteSocketIfNeeded();//确保和Zygote通信的socket已被打开
- try {
- /**
- * See com.android.internal.os.ZygoteInit.readArgumentList()
- * Presently the wire format to the zygote process is:
- * a) a count of arguments (argc, in essence)
- * b) a number of newline-separated argument strings equal to count
- *
- * After the zygote process reads these it will write the pid of
- * the child or -1 on failure, followed by boolean to
- * indicate whether a wrapper process was used.
- */
- sZygoteWriter.write(Integer.toString(args.size()));
- sZygoteWriter.newLine();
- int sz = args.size();
- for (int i = 0; i < sz; i++) {//发送请求参数到Zygote
- String arg = args.get(i);
- if (arg.indexOf('\n') >= 0) {
- throw new ZygoteStartFailedEx(
- "embedded newlines not allowed");
- }
- sZygoteWriter.write(arg);
- sZygoteWriter.newLine();
- }
- sZygoteWriter.flush();
- // Should there be a timeout on this?
- ProcessStartResult result = new ProcessStartResult();
- result.pid = sZygoteInputStream.readInt();//Zygote处理完成会返回子进程的pid(即要创建的进程)
- if (result.pid < 0) {
- throw new ZygoteStartFailedEx("fork() failed");
- }
- result.usingWrapper = sZygoteInputStream.readBoolean();
- return result;
- } catch (IOException ex) {
- try {
- if (sZygoteSocket != null) {
- sZygoteSocket.close();
- }
- } catch (IOException ex2) {
- // we're going to fail anyway
- Log.e(LOG_TAG,"I/O exception on routine close", ex2);
- }
- sZygoteSocket = null;
- throw new ZygoteStartFailedEx(ex);
- }
- }
到这里位置,客户端请求Zygote创建进程的请求就发送出去了,Zygote会返回进行的pid给客户端(ActivityMangerService)。由于ActivityMangerService在SystemServer进程中,所以这里即SystemServer进程通过socket向Zygote发送了信息。
接下来,我们看一下看一下Zygote是如何处理客户端请求的。
处理客户端请求
- /**
- * Runs the zygote process's select loop. Accepts new connections as
- * they happen, and reads commands from connections one spawn-request's
- * worth at a time.
- *
- * @throws MethodAndArgsCaller in a child process when a main() should
- * be executed.
- */
- private static void runSelectLoop() throws MethodAndArgsCaller {
- <span style="white-space:pre"> </span>......
- <span style="white-space:pre"> </span>
- while (true) {//死循环
- ......
- if (index < 0) {
- throw new RuntimeException("Error in select()");
- } else if (index == 0) {//index==0表示selcet接收到的是Zygote的socket的事件
- ZygoteConnection newPeer = acceptCommandPeer();
- peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
- } else {//调用ZygoteConnection对象的runOnce方法,ZygoteConnection是在index == 0时被添加到peers的
- boolean done;
- done = peers.get(index).runOnce();
- if (done) {
- peers.remove(index);
- fds.remove(index);
- }
- }
- }
- }
每当有请求过来时,Zygote都会调用ZygoteConnection的runOnce()方法处理:
@/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
- /**
- * Reads one start command from the command socket. If successful,
- * a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
- * exception is thrown in that child while in the parent process,
- * the method returns normally. On failure, the child is not
- * spawned and messages are printed to the log and stderr. Returns
- * a boolean status value indicating whether an end-of-file on the command
- * socket has been encountered.
- *
- * @return false if command socket should continue to be read from, or
- * true if an end-of-file has been encountered.
- * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main()
- * method in child process
- */
- boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
- String args[];
- Arguments parsedArgs = null;
- FileDescriptor[] descriptors;
- try {
- args = readArgumentList();//读取客户端发送过来的参数
- descriptors = mSocket.getAncillaryFileDescriptors();
- } catch (IOException ex) {
- Log.w(TAG, "IOException on command socket " + ex.getMessage());
- closeSocket();
- return true;
- }
- if (args == null) {
- // EOF reached.
- closeSocket();
- return true;
- }
- /** the stderr of the most recent request, if avail */
- PrintStream newStderr = null;
- if (descriptors != null && descriptors.length >= 3) {
- newStderr = new PrintStream(
- new FileOutputStream(descriptors[2]));
- }
- int pid = -1;
- FileDescriptor childPipeFd = null;
- FileDescriptor serverPipeFd = null;
- try {
- parsedArgs = new Arguments(args);
- applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
- applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
- applyCapabilitiesSecurityPolicy(parsedArgs, peer, peerSecurityContext);
- applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
- applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
- applyDebuggerSystemProperty(parsedArgs);
- applyInvokeWithSystemProperty(parsedArgs);
- int[][] rlimits = null;
- if (parsedArgs.rlimits != null) {
- rlimits = parsedArgs.rlimits.toArray(intArray2d);
- }
- if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
- FileDescriptor[] pipeFds = Libcore.os.pipe();
- childPipeFd = pipeFds[1];
- serverPipeFd = pipeFds[0];
- ZygoteInit.setCloseOnExec(serverPipeFd, true);
- }
- //fork一个新进程
- pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
- parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
- parsedArgs.niceName);
- } catch (IOException ex) {
- logAndPrintError(newStderr, "Exception creating pipe", ex);
- } 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);
- }
- }
Zygote在处理客户端请求时会fork一个新的进程,接下来首先看一下handleChildProc()方法:
- /**
- * Handles post-fork setup of child proc, closing sockets as appropriate,
- * reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller
- * if successful or returning if failed.
- *
- * @param parsedArgs non-null; zygote args
- * @param descriptors null-ok; new file descriptors for stdio if available.
- * @param pipeFd null-ok; pipe for communication back to Zygote.
- * @param newStderr null-ok; stream to use for stderr until stdio
- * is reopened.
- *
- * @throws ZygoteInit.MethodAndArgsCaller on success to
- * trampoline to code that invokes static main.
- */
- private void handleChildProc(Arguments parsedArgs,
- FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
- throws ZygoteInit.MethodAndArgsCaller {
- closeSocket();//关闭子进程中,从Zygote fork过来的服务端socket
- ZygoteInit.closeServerSocket();
- .....
- if (parsedArgs.niceName != null) {
- Process.setArgV0(parsedArgs.niceName);
- }
- if (parsedArgs.runtimeInit) {//从startViaZygote可知传入了--runtime-init参数,所以这里为true
- if (parsedArgs.invokeWith != null) {//没有传入--invoke-with,所以这里走的是else的逻辑
- WrapperInit.execApplication(parsedArgs.invokeWith,
- parsedArgs.niceName, parsedArgs.targetSdkVersion,
- pipeFd, parsedArgs.remainingArgs);
- } else {
- RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
- parsedArgs.remainingArgs);
- }
- } else {
- ......
- }
- }
zygoteInit()方法的实现在RuntimeInit类中:
@/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
- /**
- * The main function called when started through the zygote process. This
- * could be unified with main(), if the native code in nativeFinishInit()
- * were rationalized with Zygote startup.<p>
- *
- * Current recognized args:
- * <ul>
- * <li> <code> [--] <start class name> <args>
- * </ul>
- *
- * @param targetSdkVersion target SDK version
- * @param argv arg strings
- */
- 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系统
- /*
- * 初始化了一些系统属性,其中最重要的一点就是设置了一个未捕捉异常的handler,
- * 当代码有任何未知异常,就会执行它,
- * 调试过Android代码的同学经常看到的"*** FATAL EXCEPTION IN SYSTEM PROCESS" 打印就出自这里
- */
- commonInit();
- /*
- * 最终会调用app_main的onZygoteInit函数
- * 这里的作用是在新进程中引入Binder,也就说通过nativeZygoteInit以后,新的进程就可以使用Binder进程通信了
- */
- nativeZygoteInit();
- applicationInit(targetSdkVersion, argv);//应用初始化
- }
接下来继续分析applicationInit(),走完进程启动的整个过程,然后再回头分析一下commonInit和nativeZygoteInit的实现。applicationInit的实现如下:
- 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);
- }
在applicationInit()的最后,会通过调用invokeStaticMain来调用args.startClass这个类的main()方法。在前面介绍socket的客户端代码时,在startProcessLocked()中传入的这个类为
- /**
- * Invokes a static "main(argv[]) method on class "className".
- * Converts various failing exceptions into RuntimeExceptions, with
- * the assumption that they will then cause the VM instance to exit.
- *
- * @param className Fully-qualified class name
- * @param argv Argument vector for main()
- */
- 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);
- }
这个方法本身功能就是调用ActivityThread类的main(),没什么可说的。不过需要注意一下的是这里的调用方式十分特别,并没有采取常规的反射调用,而是通过抛出异常的方式调用ActivityThread的main()函数。这里抛出的ZygoteInit.MethodAndArgsCaller异常会在ZygoteInit.main()中被捕获处理。
- public static void main(String argv[]) {
- try {
- ......
- } catch (MethodAndArgsCaller caller) {
- caller.run();
- } catch (RuntimeException ex) {
- ......
- }
- }
这里需要注意的是:捕获异常是在子进程(即新的进程,不是Zygote进程)中的动作。还记得前面介绍的runOnce()方法吗?我们在runOnce中创建了一个新的进程。如果读者还有不明白这里为什么是在子进程,可以自行学习Linux
fork()的原理。好了,继续..... 看一下MethodAndArgsCaller的代码:
@/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
- /**
- * Helper exception class which holds a method and arguments and
- * can call them. This is used as part of a trampoline to get rid of
- * the initial process setup stack frames.
- */
- public static class MethodAndArgsCaller extends Exception
- 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);
- }
- }
- }
可以看出最后还是会调用invoke方法通过反射的方式调用ActivityThread的main方法。
到了这里,相信大家都会有一个疑问:既然最后还是通过invoke来反射调用main方法,那绕这一大圈子到底在折腾什么?
有疑问的读者,有没有去思考过另外一个问题:我们为什么要通过Zygote去创建进程,而不是直接创建一个新的进程出来呢?这就要从Zygote创建进程的机制来解释。相信我们还记得在ZygoteInit的main函数中我们通过preload来预加载类和资源。所以这些被预加载的类和资源都存在于Zygote进程中。在通过Zygote创建进程时,我们是通过fork来创建的。 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同,相当于克隆了一个自己。所以,Zygote通过fork的方式创建新的应用进程的同时,会将对系统的(主要是framework中的)一些类和资源的引用同时复制给子进程,这样子进程中就可以使用这些资源了。这也是为什么所有的应用程序可以共享Framework中的类和资源的原因。
在明白了Zygote机制后,对应为什么这里会以抛出异常的方式调用ActivityThread(应用程序入口)的main()方法,就变得容易理解了。在Java中,我们进行一些列的方法调用的时候,系统会为我们在内存中维护一个调用栈,栈底是发起调用的方法,栈顶是当前正在被调用的方法。在栈顶的方法调用完成后,会逐级返回调用它的方法,最后调用会回到最开始的方法中,然后调用栈就被销毁了。在Zygote处理客户端事件的时候,沿着各种方法一路调用下来,如果在调用ActivityThread中的main()时,直接使用invoke,那么在invoke结束后,整个调用过程会递归返回,最后发起方得到调用结果,调用栈被销毁。然后每次的调用都会重复刚才的那个过程,这就造成了极大的浪费。采用异常的方式,可以保证调用栈不会被销毁,这样每次fork时就可以共享。
好了,到此为止Zygote的分裂过程就介绍完成了。
Zygote进程【2】——Zygote的分裂的更多相关文章
- Android系统启动流程(二)解析Zygote进程启动过程
1.Zygote简介 在Android系统中,DVM(Dalvik虚拟机).应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器.它通过 ...
- Zygote进程介绍【转】
本文转载自:http://blog.csdn.net/yangwen123/article/details/17258023 Zygote进程介绍 在Android系统中,存在不同的服务,这些服务 ...
- Zygote进程【3】——SystemServer的诞生
在ZygoteInit的main()方法中做了几件大事,其中一件便是启动Systemserver进程,代码如下: @/frameworks/base/core/Java/com/Android/int ...
- Android 内核初识(5)Zygote进程
简介 Zygote本身是一个Native的应用程序,和驱动.内核等均无关系.Zygote是由init进程根据init.rc文件中的配置项而创建的. zygote最初的名字叫“app_process”, ...
- Android4.4的zygote进程(下)
3.2.4启动Android系统服务——startSystemServer() 接下来就是启动Android的重头戏了,此时ZygoteInit的main()函数会调用startSystemServe ...
- Android4.4的zygote进程(上)
1背景 前些天为了在科室做培训,我基于Android 4.4重新整理了一份关于zygote的文档.从技术的角度看,这几年zygote并没有出现什么大的变化,所以如果有人以前研究过zygote,应该不会 ...
- Zygote进程【1】——Zygote的诞生
在Android中存在着C和Java两个完全不同的世界,前者直接建立在Linux的基础上,后者直接建立在JVM的基础上.zygote的中文名字为"受精卵",这个名字很好的诠释了zy ...
- Android4.4 Framework分析——Zygote进程的启动过程
Android启动过程中的第一个进程init.在启动过程中会启动两个关键的系统服务进程ServiceManager和Zygote. 本文要介绍的就是Zygote进程的启动,Zygote俗称孵化器,专门 ...
- Android Zygote进程是如何fork一个APP进程的
进程创建流程 不管从桌面启动应用还是应用内启动其它应用,如果这个应用所在进程不存在的话,都需要发起进程通过Binder机制告诉system server进程的AMS system server进程的A ...
随机推荐
- jQuery倒计时
Css------------------------------------------------------------------------------------------------- ...
- Spring AOP 四大通知
Spring AOP 四大通知 Spring 3.X 以前 1.前置通知,实现 MethodBeforeAdvice 接口,重写 public void before(Method metho ...
- Nutz中那些好用的工具类
Nutz 是国产的精品开源框架,它全无依赖,只以1兆多的身材,就可以实现SSH全部功能的90%以上.内容主要涵盖了:Ioc.Aop.MVC.Dao.Json等WEB开发的方方面面. 它不仅轻巧,而且 ...
- symfony2 controller
1.基本概念 一次http请求 输入(Request):header信息.get信息.post数据等 输出(Response):symfony经过处理返回的信息,包括页面.json字符串.URL ...
- Linux 僵尸进程查杀
僵尸进程概念 僵尸进程(Zombie process)通俗来说指那些虽然已经终止的进程,但仍然保留一些信息,等待其父进程为其收尸. 书面形式一点:一个进程结束了,但是他的父进程没有等待(调用wait ...
- ORACLE查看表空间对象
ORACLE如何查看表空间存储了那些数据库对象呢?可以使用下面脚本简单的查询表空间存储了那些对象: SELECT TABLESPACE_NAME AS TABLESPACE_NAME ...
- Apache安装问题:configure: error: APR not found . Please read the documentation
Linux上安装Apache时,编译出现错误: checking for APR... no configure: error: APR not found . Please read the do ...
- 按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有确定位
package com.hanqi.test; public class Rect { ; ; public double getWidth() { return width; } public vo ...
- 烂泥:nginx负载均衡
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 今天我们来学习下有关nginx的负载均衡配置.nginx的负载均衡是通过nginx的upstream模块和proxy_pass反向代理来实现的. 说明: ...
- 烂泥:Windows下安装与配置Nginx web服务器
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 前几篇文章,我们使用nginx都是在linux环境下,今天由于工作的需要.需要在windows环境也使用nginx搭建web服务器. 下面记录下有关ng ...