Android7.0系统进入Zygote进程

 SystemServer进程Android用户空间核心的的进程, framework层的很多services都是在SystemServer中进行创建并启动的. SystemServer也是由Zygote进行孵化的. 在将解启动zygote进程一文中知道启动zygote就会进入framework/cmds/app_process/app_main.cpp的main函数中

init.rczygote有四个参数:-Xzygote /system/bin --zygote --start-system-server,各自的意义如下:

-Xzygote:该参数将作为虚拟机启动时所需的参数;

/system/bin:代表虚拟机程序所在目录;

--zygote:指明以ZygoteInit.Java类中的main函数作为虚拟机执行入口;

--start-system-server:告诉Zygote进程启动SystemServer进程;

app_main.cppmain函数中会使用这些参数。前两个参数主要对虚拟机的设置,后面的参数主要处理systemServer

[cpp]  view plain  copy
  1. #if defined(__LP64__)           //判断系统为64为还是32为, 进行赋予不同的进程名  
  2. static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";  
  3. static const char ZYGOTE_NICE_NAME[] = "zygote64";  
  4. #else  
  5. static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";  
  6. static const char ZYGOTE_NICE_NAME[] = "zygote";  
  7. #endif  

[cpp]  view plain  copy
  1. // Parse runtime arguments.  Stop at first unrecognized option. //解析运行时的参数,从解析init.rc中获得  
  2. bool zygote = false;  
  3. bool startSystemServer = false;  
  4. bool application = false;  
  5. String8 niceName;  
  6. String8 className;  
  7.   
  8. ++i;  // Skip unused "parent dir" argument.  
  9. while (i < argc) {  
  10.     const char* arg = argv[i++];  
  11.     if (strcmp(arg, "--zygote") == 0) {  
  12.         zygote = true;    //在zygote模式中启动  
  13.         niceName = ZYGOTE_NICE_NAME; //设置进程的名字  
  14.     } else if (strcmp(arg, "--start-system-server") == 0) {  
  15.         startSystemServer = true;   //启动System Server  
  16.     } else if (strcmp(arg, "--application") == 0) {  
  17.         application = true;          //在application模式启动  
  18.     } else if (strncmp(arg, "--nice-name=", 12) == 0) {  
  19.         niceName.setTo(arg + 12);     //参数中有进程名,就设置  
  20.     } else if (strncmp(arg, "--", 2) != 0) {  
  21.         className.setTo(arg);   //设置className  
  22.         break;  
  23.     } else {  
  24.         --i;  
  25.         break;  
  26.     }  
  27. }  

根据上面获取的参数, 知道我们正在zygote mode

[cpp]  view plain  copy
  1. // We're in zygote mode.  
  2. maybeCreateDalvikCache(); //创建data/dalvik-cache,设置环境  
  3.   
  4. if (startSystemServer) {  //startSystemServer为true  
  5.     args.add(String8("start-system-server"));  
  6. }  
  7.   
  8. char prop[PROP_VALUE_MAX];  
  9. if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {  
  10.     LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",  
  11.         ABI_LIST_PROPERTY);  
  12.     return 11;  
  13. }  
  14.   
  15. String8 abiFlag("--abi-list=");  
  16. abiFlag.append(prop);  
  17. args.add(abiFlag);  
  18.   
  19. // In zygote mode, pass all remaining arguments to the zygote  
  20. // main() method.  
  21. for (; i < argc; ++i) {  
  22.     args.add(String8(argv[i])); //将所有参数添加如args中  
  23. }  
根据rc文件中zygote的设置可以知道zygote为true
[cpp]  view plain  copy
  1. if (zygote) {  
  2.     runtime.start("com.android.internal.os.ZygoteInit", args, zygote); //调用ZygoteInit  
  3. else if (className) {  
  4.     runtime.start("com.android.internal.os.RuntimeInit", args, zygote);  
  5. else {  
  6.     fprintf(stderr, "Error: no class name or --zygote supplied.\n");  
  7.     app_usage();  
  8.     LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");  
  9.     return 10;  
  10. }  

由于AppRuntime派生与AndroidRuntime,故会调用AndroidRuntime的start函数,之后会启动虚拟机,并且对虚拟机进行初始化,注册JNI函数。最后根据在app_main中传递过来的启动类参数,获取它的静态main函数,启动ZygoteInit类的main函数。代码位置frameworks/base/core/jni/AndroidRuntime.cpp

[cpp]  view plain  copy
  1. /* 
  2.  * Start the Android runtime.  This involves starting the virtual machine 
  3.  * and calling the "static void main(String[] args)" method in the class 
  4.  * named by "className". 
  5.  * 
  6.  * Passes the main function two arguments, the class name and the specified 
  7.  * options string. 
  8.  */  
  9. void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)  
  10. {  
  11.     ALOGD(">>>>>> START %s uid %d <<<<<<\n",  
  12.             className != NULL ? className : "(unknown)", getuid());  //在main.log中输出需要启动的className  
  13.   
  14.     static const String8 startSystemServer("start-system-server");  
  15.   
  16.     /* 
  17.      * 'startSystemServer == true' means runtime is obsolete and not run from 
  18.      * init.rc anymore, so we print out the boot start event here. 
  19.      */  
  20.     for (size_t i = 0; i < options.size(); ++i) {  
  21.         if (options[i] == startSystemServer) {  
  22.            /* track our progress through the boot sequence */  
  23.            const int LOG_BOOT_PROGRESS_START = 3000;  //在event log中输出android启动的时间  
  24.            LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));  
  25.         }  
  26.     }  
  27.   
  28.     ...........  
  29.   
  30.     /* start the virtual machine */  
  31.     JniInvocation jni_invocation;  
  32.     jni_invocation.Init(NULL);  
  33.     JNIEnv* env;  
  34.     if (startVm(&mJavaVM, &env, zygote) != 0) {  //启动虚拟机  
  35.         return;  
  36.     }  
  37.     onVmCreated(env);   //对虚拟机进行初始化  
  38.   
  39.     /* 
  40.      * Register android functions. 
  41.      */  
  42.     if (startReg(env) < 0) {  //注册JNI函数  
  43.         ALOGE("Unable to register all android natives\n");   
  44.         return;  
  45.     }  
  46.   
  47.     .......  
  48.     /* 
  49.      * Start VM.  This thread becomes the main thread of the VM, and will 
  50.      * not return until the VM exits. 
  51.      */  
  52.     char* slashClassName = toSlashClassName(className);  
  53.     jclass startClass = env->FindClass(slashClassName);  
  54.     if (startClass == NULL) {  
  55.         ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);  
  56.         /* keep going */  
  57.     } else {  
  58.         jmethodID startMeth = env->GetStaticMethodID(startClass, "main",  
  59.             "([Ljava/lang/String;)V");  
  60.         if (startMeth == NULL) {  
  61.             ALOGE("JavaVM unable to find main() in '%s'\n", className);  
  62.             /* keep going */  
  63.         } else {  
  64.             env->CallStaticVoidMethod(startClass, startMeth, strArray);  //调用ZygoteInit的main函数  
  65.   
  66. #if 0  
  67.             if (env->ExceptionCheck())  
  68.                 threadExitUncaughtException(env);  
  69. #endif  
  70.         }  
  71.     }  
  72.     free(slashClassName);    
  73.   
  74.     ALOGD("Shutting down VM\n");  //如果系统死掉会走到这里  
  75.     if (mJavaVM->DetachCurrentThread() != JNI_OK)  
  76.         ALOGW("Warning: unable to detach main thread\n");  
  77.     if (mJavaVM->DestroyJavaVM() != 0)  
  78.         ALOGW("Warning: VM did not shut down cleanly\n");  
  79. }  

在调用完ZygoteInit的main函数后,Zygote就进入了Java世界。


ZygoteInit代码位置frameworks/base/core/java/com/android/internal/os/ZygoteInit.java , 

在ZygoteInit的main函数中首先将从底层中传过来的参数获取出来.

[cpp]  view plain  copy
  1. boolean startSystemServer = false;  
  2. String socketName = "zygote";      //socketName为zygote  
  3. String abiList = null;  
  4. for (int i = 1; i < argv.length; i++) {  
  5.     if ("start-system-server".equals(argv[i])) {  
  6.         startSystemServer = true;        //start-system-server在参数列表中,故为true  
  7.     } else if (argv[i].startsWith(ABI_LIST_ARG)) {  
  8.         abiList = argv[i].substring(ABI_LIST_ARG.length()); //设置abiList  
  9.     } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { //如果参数列表有socketName,就重新设置socketName  
  10.         socketName = argv[i].substring(SOCKET_NAME_ARG.length());  
  11.     } else {  
  12.         throw new RuntimeException("Unknown command line argument: " + argv[i]);  
  13.     }  
  14. }  

在ZygoteInit中通过RegisterZygoteSocket()进行注册Socket,用于进程间通信。

[cpp]  view plain  copy
  1. /** 
  2.  * Registers a server socket for zygote command connections 
  3.  * 
  4.  * @throws RuntimeException when open fails 
  5.  */  
  6. private static void registerZygoteSocket(String socketName) {  
  7.     if (sServerSocket == null) {  
  8.         int fileDesc;  
  9.         final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; //设置完整的socketName  
  10.         try {  
  11.             String env = System.getenv(fullSocketName);  //获取环境变量  
  12.             fileDesc = Integer.parseInt(env);    
  13.         } catch (RuntimeException ex) {  
  14.             throw new RuntimeException(fullSocketName + " unset or invalid", ex);  
  15.         }  
  16.   
  17.         try {  
  18.             FileDescriptor fd = new FileDescriptor();  
  19.             fd.setInt$(fileDesc);   //设置文件描述符  
  20.             sServerSocket = new LocalServerSocket(fd); //根据文件描述符创建Server Socket  
  21.         } catch (IOException ex) {     
  22.             throw new RuntimeException(  
  23.                     "Error binding to local socket '" + fileDesc + "'", ex);  
  24.         }  
  25.     }  
  26. }  
    其中Socket的监听方式为使用Linux系统调用select()函数监听Socket文件描述符,当该文件描述符上有数据时,自动触发中断,在中断处理函数中去读取文件描述符中的数据。

    在Android系统中有很多的公共资源,所有的程序都会需要。而Zygote创建应用程序进程过程其实就是复制自身进程地址空间作为应用程序进程的地址空间,因此在Zygote进程中加载的类和资源都可以共享给所有由Zygote进程孵化的应用程序。所以就可以在Zygote中对公共类与资源进行加载,当应用程序启动时只需要加载自身特有的类与资源就行了,提高了应用软件的启动速度,这也看出面向对象编程中继承关系的好处。

[cpp]  view plain  copy
  1. static void preload() {  
  2.     Log.d(TAG, "begin preload");  
  3.     Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");  //Systrace开始tag  
  4.     beginIcuCachePinning();  
  5.     Trace.traceEnd(Trace.TRACE_TAG_DALVIK);   //systrace结束tag  
  6.     Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");  
  7.     preloadClasses();     //预加载Classes  
  8.     Trace.traceEnd(Trace.TRACE_TAG_DALVIK);  
  9.     Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");  
  10.     preloadResources();  //预加载resources  
  11.     Trace.traceEnd(Trace.TRACE_TAG_DALVIK);  
  12.     Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");  
  13.     preloadOpenGL();    //预加载openGL  
  14.     Trace.traceEnd(Trace.TRACE_TAG_DALVIK);  
  15.     preloadSharedLibraries();    //预加载共享类库  
  16.     preloadTextResources();     //预加载文本资源  
  17.     // Ask the WebViewFactory to do any initialization that must run in the zygote process,  
  18.     // for memory sharing purposes.  
  19.     WebViewFactory.prepareWebViewInZygote();  
  20.     endIcuCachePinning();  
  21.     warmUpJcaProviders();  
  22.     Log.d(TAG, "end preload");  
  23. }  
需要预加载的classes在手机中system/etc/preloaded-classes里面可以看到
[cpp]  view plain  copy
  1.     /** 
  2.      * The path of a file that contains classes to preload. 
  3.      */  
  4.     private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";  
  5.   
  6.     private static void preloadClasses() {  
  7.         final VMRuntime runtime = VMRuntime.getRuntime();  
  8.   
  9.         InputStream is;  
  10.         try {  
  11.             is = new FileInputStream(PRELOADED_CLASSES);   //将classes文件转变为文件输入流  
  12.         } catch (FileNotFoundException e) {  
  13.             Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");  
  14.             return;  
  15.         }  
  16.   
  17.         Log.i(TAG, "Preloading classes...");  
  18.         long startTime = SystemClock.uptimeMillis();   //开始预加载时间  
  19.         //.........  
  20.         try {  
  21.             BufferedReader br  
  22.                 = new BufferedReader(new InputStreamReader(is), 256);   //封装成BufferReader  
  23.   
  24.             int count = 0;  
  25.             String line;  
  26.             while ((line = br.readLine()) != null) {   
  27.                 // Skip comments and blank lines.  
  28.                 line = line.trim();  
  29.                 if (line.startsWith("#") || line.equals("")) {  //将没有用的行过滤掉  
  30.                     continue;  
  31.                 }  
  32.   
  33.                 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClass " + line);  
  34.                 try {  
  35.                     if (false) {  
  36.                         Log.v(TAG, "Preloading " + line + "...");  
  37.                     }  
  38.                     // Load and explicitly initialize the given class. Use  
  39.                     // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups  
  40.                     // (to derive the caller's class-loader). Use true to force initialization, and  
  41.                     // null for the boot classpath class-loader (could as well cache the  
  42.                     // class-loader of this class in a variable).  
  43.                     Class.forName(line, true, null);   //用反射将每一行的类没转化为class  
  44.                     count++;  
  45.                 } catch (ClassNotFoundException e) {  
  46.                     Log.w(TAG, "Class not found for preloading: " + line);  
  47.                 } catch (UnsatisfiedLinkError e) {  
  48.                     Log.w(TAG, "Problem preloading " + line + ": " + e);  
  49.                 } catch (Throwable t) {  
  50.                     Log.e(TAG, "Error preloading " + line + ".", t);  
  51.                     if (t instanceof Error) {  
  52.                         throw (Error) t;  
  53.                     }  
  54.                     if (t instanceof RuntimeException) {  
  55.                         throw (RuntimeException) t;  
  56.                     }  
  57.                     throw new RuntimeException(t);  
  58.                 }  
  59.                 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);  
  60.             }  
  61.   
  62.             Log.i(TAG, "...preloaded " + count + " classes in "  
  63.                     + (SystemClock.uptimeMillis()-startTime) + "ms.");  //计算预加载classes一共花了多长时间  
  64.   //......  
  65. }  
[cpp]  view plain  copy
  1. private static void preloadResources() {  
  2.       final VMRuntime runtime = VMRuntime.getRuntime();  
  3.   
  4.       try {  
  5.           mResources = Resources.getSystem();  
  6.           mResources.startPreloading();  
  7.           if (PRELOAD_RESOURCES) {  
  8.               Log.i(TAG, "Preloading resources...");  
  9.   
  10.               long startTime = SystemClock.uptimeMillis();  //记录开始预加载resources时间点  
  11.               TypedArray ar = mResources.obtainTypedArray(   //所需要加载的资源,其实就是在framework/base/core/res/res/values/arrays.xml中进行定义的  
  12.                       com.android.internal.R.array.preloaded_drawables);  //获取需要预加载的drawables  
  13.               int N = preloadDrawables(ar);      //预加载drawables  
  14.               ar.recycle();  
  15.               Log.i(TAG, "...preloaded " + N + " resources in "  
  16.                       + (SystemClock.uptimeMillis()-startTime) + "ms.");   //预加载drawables耗时情况  
  17.   
  18.               startTime = SystemClock.uptimeMillis();     //开始预加载colorState时间点  
  19.               ar = mResources.obtainTypedArray(  
  20.                       com.android.internal.R.array.preloaded_color_state_lists);   //获取预加载的color state lists  
  21.               N = preloadColorStateLists(ar);    //预加载color state  
  22.               ar.recycle();  
  23.               Log.i(TAG, "...preloaded " + N + " resources in "  
  24.                       + (SystemClock.uptimeMillis()-startTime) + "ms.");  //预加载resoures耗时  
  25.   
  26.               if (mResources.getBoolean(  
  27.                       com.android.internal.R.bool.config_freeformWindowManagement)) {  
  28.                   startTime = SystemClock.uptimeMillis();  
  29.                   ar = mResources.obtainTypedArray(  
  30.                           com.android.internal.R.array.preloaded_freeform_multi_window_drawables);  
  31.                   N = preloadDrawables(ar);  
  32.                   ar.recycle();  
  33.                   Log.i(TAG, "...preloaded " + N + " resource in "  
  34.                           + (SystemClock.uptimeMillis() - startTime) + "ms.");  
  35.               }  
  36.           }  
  37.           mResources.finishPreloading();  
  38.       } catch (RuntimeException e) {  
  39.           Log.w(TAG, "Failure preloading resources", e);  
  40.       }  
  41.   }  
Android7.0在zygoteInit中对线程的使用做了限制,不让在zygote中新建线程
[cpp]  view plain  copy
  1. ZygoteHooks.stopZygoteNoThreadCreation();  //禁止创建线程  
Google代码提交历史
[cpp]  view plain  copy
  1. commit 1ef8aef260c19236be023c429b41a46e7f5da8b0  
  2. Author: Andreas Gampe <agampe@google.com>  
  3. Date:   Mon Apr 11 08:39:52 2016 -0700  
  4.   
  5.     Frameworks/base: Add no-thread marking to zygote  
  6.       
  7.     Use ZygoteHooks code to mark zygote initialization to not be  
  8.     allowed to create threads. This is helpful when new classes are  
  9.     found to be used by apps but cannot be preloaded as they spawn  
  10.     threads.   //根据注释可以看出,主要是由于担心用户新建线程提高预加载速度  
  11.                      //但是可能没做好同步工作, 当有的应用需要预加载的资源,但是多线程情况下还没有加载,发生问题  
  12.     Bug: 27248115  
  13.     Change-Id: I1dc3620d9e7d0054c672b993d89459fc4b353dfc  
  14.   
  15. diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java  
  16. index 5980ab6..78b5d61 100644  
  17. --- a/core/java/com/android/internal/os/ZygoteInit.java  
  18. +++ b/core/java/com/android/internal/os/ZygoteInit.java  
  19. @@ -43,6 +43,7 @@ import com.android.internal.os.InstallerConnection.InstallerException;  
  20.  import dalvik.system.DexFile;  
  21.  import dalvik.system.PathClassLoader;  
  22.  import dalvik.system.VMRuntime;  
  23. +import dalvik.system.ZygoteHooks;  
  24.    
  25.  import libcore.io.IoUtils;  
  26.    
  27. @@ -597,6 +598,10 @@ public class ZygoteInit {  
  28.      }  
  29.    
  30.      public static void main(String argv[]) {  
  31. +        // Mark zygote start. This ensures that thread creation will throw  
  32. +        // an error.  
  33. +        ZygoteHooks.startZygoteNoThreadCreation();     //启动无多线程模式 .当在zygoteInit中新建线程系统挂掉  
  34. +  
  35.          try {  
  36.              Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");  
  37.              RuntimeInit.enableDdms();  
  38. @@ -648,6 +653,8 @@ public class ZygoteInit {  
  39.              // Zygote process unmounts root storage spaces.  
  40.              Zygote.nativeUnmountStorageOnInit();  
  41.    
  42. +            ZygoteHooks.stopZygoteNoThreadCreation();  //停止无多线程模式  
  43. +  
  44.              if (startSystemServer) {  
  45.                  startSystemServer(abiList, socketName);  
  46.              }  
继续往下执行,就该创建SystemServer, 在后文中将讲解.

并且循环进入监听模式, 监听创建进程的请求

[java]  view plain  copy
  1. if (startSystemServer) {   //startSysteServer为true  
  2.     startSystemServer(abiList, socketName);     
  3. }  
  4.   
  5. Log.i(TAG, "Accepting command socket connections");  
  6. runSelectLoop(abiList);     //接受应用的socket链接请求  
  7.   
  8. closeServerSocket();   //当退出循环时,系统出现问题, 所以也要将server socket关闭.  

之后Zygote等待客户端的创建进程请求.

[java]  view plain  copy
  1. /** 
  2.  * Runs the zygote process's select loop. Accepts new connections as 
  3.  * they happen, and reads commands from connections one spawn-request's 
  4.  * worth at a time. 
  5.  * 
  6.  * @throws MethodAndArgsCaller in a child process when a main() should 
  7.  * be executed. 
  8.  */  
  9. private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {  
  10.     ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();  
  11.     ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();  
  12.   
  13.     fds.add(sServerSocket.getFileDescriptor());   
  14.     peers.add(null);  
  15.   
  16.     while (true) {  
  17.         StructPollfd[] pollFds = new StructPollfd[fds.size()];  
  18.         for (int i = 0; i < pollFds.length; ++i) {  
  19.             pollFds[i] = new StructPollfd();  
  20.             pollFds[i].fd = fds.get(i);  
  21.             pollFds[i].events = (short) POLLIN;  
  22.         }  
  23.         try {  
  24.             Os.poll(pollFds, -1);  
  25.         } catch (ErrnoException ex) {  
  26.             throw new RuntimeException("poll failed", ex);  
  27.         }  
  28.         for (int i = pollFds.length - 1; i >= 0; --i) {  
  29.             if ((pollFds[i].revents & POLLIN) == 0) {  
  30.                 continue;  
  31.             }  
  32.             if (i == 0) {  
  33.                 ZygoteConnection newPeer = acceptCommandPeer(abiList);  
  34.                 peers.add(newPeer);  
  35.                 fds.add(newPeer.getFileDesciptor());  
  36.             } else {  
  37.                 boolean done = peers.get(i).runOnce();  
  38.                 if (done) {  
  39.                     peers.remove(i);  
  40.                     fds.remove(i);  
  41.                 }  
  42.             }  
  43.         }  
  44.     }  
  45. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值