dvm,app进程,linux进程三者关系

DVM指 dalivk 的虚拟机。每一个 Android 应用程序都在它自己的进程中运行,都拥有一个独立的 Dalvik 虚拟机实例。而每一个 DVM 都是在 Linux 中的一个进程,所以说可以认为是同一个概念

Zygote进程与app进程关系

Zygote是java层的进程即它也拥有一个独立的Dalvik 虚拟机实例,它是被linux层的第一个用户空间Init进程所启动的,它的主要作用就是用来孵化app进程系统进程
fork一个app进程,是通过ActivityManagerService类向Zygote发出fork命令,ActivityManagerService是在系统进程,但是Zygote处于自己的进程中,它们之间的通信没有采用binder机制,而是采用了socket机制,因此我们可以把Zygote称为一个孵化server,ActivityMamagerService称为一个client

下面的图描述了上面的过程

涉及到的类

我们先来梳理这个过程中使用到的类,并且这些类是做什么的

以server和client2个维度来归纳这些类

Zygote进程启动分析

大家都知道android系统的Zygote进程是所有的android进程的父进程,包括SystemServer和各种应用进程都是通过Zygote进程fork出来的。Zygote(孵化)进程相当于是android系统的根进程,后面所有的进程都是通过这个进程fork出来的,而Zygote进程则是通过linux系统的init进程启动的,也就是说,android系统中各种进程的启动方式

init进程 –> Zygote进程 –> SystemServer进程 –>各种应用进程

init进程:linux的根进程,android系统是基于linux系统的,因此可以算作是整个android操作系统的第一个进程;

Zygote进程:android系统的根进程,主要作用:可以作用Zygote进程fork出SystemServer进程和各种应用进程;

SystemService进程:主要是在这个进程中启动系统的各项服务,比如ActivityManagerService,PackageManagerService,WindowManagerService服务等等;

各种应用进程:启动自己编写的客户端应用时,一般都是重新启动一个应用进程,有自己的虚拟机与运行环境;

Zygote就是进程init启动起来的。Android中所有应用程序进程,以及运行系统关键服务的System进程都是由Zygote创建的。它通过复制自身的形式创建其它进程。Zygote在启动时会在内部创建一个虚拟机实例,因此,通过复制Zygote得到的其它应用程序进程和System进程都可以快速地在内部获得一个虚拟机地拷贝。Zygote启动完成后就立即将System进程启动,以便各种关键服务被启动运行

  1. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
  2. class main
  3. socket zygote stream 660 root system
  4. onrestart write /sys/android_power/request_state wake
  5. onrestart write /sys/power/state on
  6. onrestart restart media
  7. onrestart restart netd

写到zygote是由init进程解析init.rc(以init.zygote32.rc为例)文件启动的,启动的过程传入了四个参数。分别是-Xzygote/system/bin--zygote--start-system-server

  • 虚拟机参数以"-"开头,上边的"-Xzygote"即为虚拟机参数,在启动虚拟机时传递给虚拟机
  • 运行目录即app_process可执行程序所在的目录,一般是在/system/bin
  • 参数以"--"开头,"--zygote"表示启动zygote进程,"-start-system-server-"表示启动system server"--application"表示以普通进程方式执行java代码。
  • java类,将要执行的java类,必须有一个静态方法。但是如果参数中有"--zygote"时将会忽略该参数,固定的执行zygoteInit类。

Zygote进程能够重启的地方:

  • servicemanager进程被杀; (onresart)
  • surfaceflinger进程被杀; (onresart)
  • Zygote进程自己被杀; (oneshot=false)
  • system_server进程被杀; (waitpid)

Zygote是由init进程通过解析init.zygote.rc文件而创建的,zygote所对应的可执行程序app_process,所对应的源文件是App_main.cpp,进程名为zygote。

前边分析中可以知道zygote要执行的程序是system/bin/app_process,它的源代码位于frameworks/base/cmds/app_process/App_main.cpp文件中

从App_main()开始,Zygote启动过程的函数调用类大致流程如下:

App_main.main

http://androidxref.com/6.0.1_r10/xref/frameworks/base/cmds/app_process/app_main.cpp

  1. int main(int argc, char* const argv[])
  2. {
  3. //传到的参数argv为“-Xzygote /system/bin --zygote --start-system-server”
  4. AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
  5. argc--; argv++; //忽略第一个参数
  6.  
  7. int i;
  8. for (i = 0; i < argc; i++) {
  9. if (argv[i][0] != '-') {
  10. break;
  11. }
  12. if (argv[i][1] == '-' && argv[i][2] == 0) {
  13. ++i;
  14. break;
  15. }
  16. runtime.addOption(strdup(argv[i]));
  17. }
  18. //参数解析
  19. bool zygote = false;
  20. bool startSystemServer = false;
  21. bool application = false;
  22. String8 niceName;
  23. String8 className;
  24. ++i;
  25. while (i < argc) {
  26. const char* arg = argv[i++];
  27. if (strcmp(arg, "--zygote") == 0) {
  28. zygote = true;
  29. //对于64位系统nice_name为zygote64; 32位系统为zygote
  30. niceName = ZYGOTE_NICE_NAME;
  31. } else if (strcmp(arg, "--start-system-server") == 0) {
  32. startSystemServer = true;
  33. } else if (strcmp(arg, "--application") == 0) {
  34. application = true;
  35. } else if (strncmp(arg, "--nice-name=", 12) == 0) {
  36. niceName.setTo(arg + 12);
  37. } else if (strncmp(arg, "--", 2) != 0) {
  38. className.setTo(arg);
  39. break;
  40. } else {
  41. --i;
  42. break;
  43. }
  44. }
  45. Vector<String8> args;
  46. if (!className.isEmpty()) {
  47. // 运行application或tool程序
  48. args.add(application ? String8("application") : String8("tool"));
  49. runtime.setClassNameAndArgs(className, argc - i, argv + i);
  50. } else {
  51. //进入zygote模式,创建 /data/dalvik-cache路径
  52. maybeCreateDalvikCache();
  53. if (startSystemServer) {
  54. args.add(String8("start-system-server"));
  55. }
  56. char prop[PROP_VALUE_MAX];
  57. if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
  58. return 11;
  59. }
  60. String8 abiFlag("--abi-list=");
  61. abiFlag.append(prop);
  62. args.add(abiFlag);
  63.  
  64. for (; i < argc; ++i) {
  65. args.add(String8(argv[i]));
  66. }
  67. }
  68.  
  69. //设置进程名
  70. if (!niceName.isEmpty()) {
  71. runtime.setArgv0(niceName.string());
  72. set_process_name(niceName.string());
  73. }
  74. if (zygote) {
  75. // 启动AppRuntime
  76. runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
  77. } else if (className) {
  78. runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
  79. } else {
  80. //没有指定类名或zygote,参数错误
  81. return 10;
  82. }
  83. }

AndroidRuntime.start

http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/jni/AndroidRuntime.cpp

  1. void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
  2. {
  3. static const String8 startSystemServer("start-system-server");
  4.  
  5. for (size_t i = 0; i < options.size(); ++i) {
  6. if (options[i] == startSystemServer) {
  7. const int LOG_BOOT_PROGRESS_START = 3000;
  8. }
  9. }
  10. const char* rootDir = getenv("ANDROID_ROOT");
  11. if (rootDir == NULL) {
  12. rootDir = "/system";
  13. if (!hasDir("/system")) {
  14. return;
  15. }
  16. setenv("ANDROID_ROOT", rootDir, 1);
  17. //主要是用来完成环境变量ANDROID_ROOT的设置,调用了getenv()方法和setenv()方法。
  18. //通过这段代码,环境变量ANDROID_ROOT的值被设置成了/system
  19. }
  20. JniInvocation jni_invocation;
  21. jni_invocation.Init(NULL);//通过jni_invocation.Init(NULL)完成jni接口的初始化
  22. JNIEnv* env;
  23. //调用startVm启动虚拟机,在startVm方法中,定义了虚拟机的一系列参数
  24. //通过property_get()方法来进行参数的设置。
  25. if (startVm(&mJavaVM, &env, zygote) != 0) {
  26. return;
  27. }
  28. onVmCreated(env);
  29. // JNI方法注册
  30. if (startReg(env) < 0) {
  31. return;
  32. }
  33. //定义了三个变量,定义参数的目的是将AndroidRuntime::start的两个参数传入到ZygoteInit的main方法
  34. jclass stringClass;
  35. jobjectArray strArray;
  36. jstring classNameStr;
  37.  
  38. //对三个变量分别进行了赋值
  39.  
  40. //等价 strArray= new String[options.size() + 1];
  41. stringClass = env->FindClass("java/lang/String");
  42. strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
  43.  
  44. //等价 strArray[0] = "com.android.internal.os.ZygoteInit"
  45. classNameStr = env->NewStringUTF(className);
  46. env->SetObjectArrayElement(strArray, 0, classNameStr);
  47.  
  48. //等价 strArray[1] = "start-system-server";
  49. // strArray[2] = "--abi-list=xxx";
  50. //其中xxx为系统响应的cpu架构类型,比如arm64-v8a.
  51. for (size_t i = 0; i < options.size(); ++i) {
  52. jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
  53. env->SetObjectArrayElement(strArray, i + 1, optionsStr);
  54. }
  55.  
  56. //将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"
  57. char* slashClassName = toSlashClassName(className);
  58. jclass startClass = env->FindClass(slashClassName);
  59. if (startClass == NULL) {
  60. ...
  61. } else {
  62. jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
  63. "([Ljava/lang/String;)V");
  64. // 调用ZygoteInit.main()方法
  65. env->CallStaticVoidMethod(startClass, startMeth, strArray);
  66. }
  67. //释放相应对象的内存空间
  68. free(slashClassName);
  69. mJavaVM->DetachCurrentThread();
  70. mJavaVM->DestroyJavaVM();
  71. }

start()是通过JNI回调java层的方法,它主要的目的是执行"com/android/internal/os/ZygoteInit"中main()方法,即frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中的main()函数。

创建虚拟机

进程内创建一个虚拟机实例,并注册一系列JNI方法。
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/jni/AndroidRuntime.cpp

  1. /* start the virtual machine. */
  2. startVM(&mJavaVM, &env);
  3. /* Register android functions. */
  4. startReg(env);

创建Java虚拟机方法的主要篇幅是关于虚拟机参数的设置,下面只列举部分在调试优化过程中常用参数。

  1. int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
  2. {
  3. // JNI检测功能,用于native层调用jni函数时进行常规检测,比较弱字符串格式是否符合要求,资源是否正确释放。该功能一般用于早期系统调试或手机Eng版,对于User版往往不会开启,引用该功能比较消耗系统CPU资源,降低系统性能。
  4. bool checkJni = false;
  5. property_get("dalvik.vm.checkjni", propBuf, "");
  6. if (strcmp(propBuf, "true") == 0) {
  7. checkJni = true;
  8. } else if (strcmp(propBuf, "false") != 0) {
  9. property_get("ro.kernel.android.checkjni", propBuf, "");
  10. if (propBuf[0] == '1') {
  11. checkJni = true;
  12. }
  13. }
  14. if (checkJni) {
  15. addOption("-Xcheck:jni");
  16. }
  17.  
  18. //虚拟机产生的trace文件,主要用于分析系统问题,路径默认为/data/anr/traces.txt
  19. parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");
  20.  
  21. //对于不同的软硬件环境,这些参数往往需要调整、优化,从而使系统达到最佳性能
  22. parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
  23. parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
  24. parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
  25. parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
  26. parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
  27. parseRuntimeOption("dalvik.vm.heaptargetutilization",
  28. heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization=");
  29. ...
  30.  
  31. //preloaded-classes文件内容是由WritePreloadedClassFile.java生成的,
  32. //在ZygoteInit类中会预加载工作将其中的classes提前加载到内存,以提高系统性能
  33. if (!hasFile("/system/etc/preloaded-classes")) {
  34. return -1;
  35. }
  36.  
  37. //初始化虚拟机
  38. if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
  39. ALOGE("JNI_CreateJavaVM failed\n");
  40. return -1;
  41. }
  42. }

在startVm方法中,定义了虚拟机的一系列参数。通过property_get()方法来进行参数的设置。

startReg

http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/jni/AndroidRuntime.cpp

  1. int AndroidRuntime::startReg(JNIEnv* env)
  2. {
  3. //设置线程创建方法为javaCreateThreadEt
  4. androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
  5.  
  6. env->PushLocalFrame(200);
  7. //进程NI方法的注册
  8. if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
  9. env->PopLocalFrame(NULL);
  10. return -1;
  11. }
  12. env->PopLocalFrame(NULL);
  13. return 0;
  14. }
  1. startReg注册JNI的代码

androidSetCreateThreadFunc虚拟机启动后startReg()过程,会设置线程创建函数指针gCreateThreadFn指向javaCreateThreadEtc.

ZygoteInit.main

接下来执行“com.android.internal.os.ZygoteInit”Java类的main方法继续执行启动。

Zygote进程启动后,ZygoteInit类的main方法会被执行

http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  1. public static void main(String argv[]) {
  2. try {
  3. // Start profiling the zygote initialization.
  4. SamplingProfilerIntegration.start();
  5.  
  6. boolean startSystemServer = false;
  7. String socketName = "zygote";
  8. String abiList = null;
  9. for (int i = 1; i < argv.length; i++) {
  10. if ("start-system-server".equals(argv[i])) {
  11. startSystemServer = true;
  12. } else if (argv[i].startsWith(ABI_LIST_ARG)) {
  13. abiList = argv[i].substring(ABI_LIST_ARG.length());
  14. } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
  15. socketName = argv[i].substring(SOCKET_NAME_ARG.length());
  16. } else {
  17. throw new RuntimeException("Unknown command line argument: " + argv[i]);
  18. }
  19. }
  20.  
  21. if (abiList == null) {
  22. throw new RuntimeException("No ABI list supplied.");
  23. }
  24. /*启动servier socket*/
  25. registerZygoteSocket(socketName);
  26. EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
  27. SystemClock.uptimeMillis());
  28.     //预加载资源,预加载耗时的类
  29. preload();
  30. EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
  31. SystemClock.uptimeMillis());
  32.  
  33. // Finish profiling the zygote initialization.
  34. SamplingProfilerIntegration.writeZygoteSnapshot();
  35.  
  36. // Do an initial gc to clean up after startup
  37. gc();
  38.  
  39. // Disable tracing so that forked processes do not inherit stale tracing tags from
  40. // Zygote.
  41. Trace.setTracingEnabled(false);
  42.  
  43. if (startSystemServer) {
  44. /*启动系统服务*/
  45. startSystemServer(abiList, socketName);
  46. }
  47.  
  48. Log.i(TAG, "Accepting command socket connections");
  49. runSelectLoop(abiList);
  50.  
  51. closeServerSocket();
  52. } catch (MethodAndArgsCaller caller) {
  53. //这行代码很重要
  54. caller.run();
  55. } catch (RuntimeException ex) {
  56. Log.e(TAG, "Zygote died with exception", ex);
  57. closeServerSocket();
  58. throw ex;
  59. }
  60. }

上面代码主要做了下面的事情:

  • registerZygoteSocket(socketName)启动一个ServerSocket
  • preload()预加载资源,预加载耗时的类
  • startSystemServer(abiList, socketName)启动系统服务,并且fork系统进程
  • runSelectLoop(abiList)监听client socket的连接

来看下registerZygoteSocket(socketName)方法

  1. private static void registerZygoteSocket(String socketName) {
  2. if (sServerSocket == null) {
  3. int fileDesc;
  4. final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
  5. try {
  6. String env = System.getenv(fullSocketName);
  7. fileDesc = Integer.parseInt(env);
  8. } catch (RuntimeException ex) {
  9. throw new RuntimeException(fullSocketName + " unset or invalid", ex);
  10. }
  11.  
  12. try {
  13. sServerSocket = new LocalServerSocket(
  14. createFileDescriptor(fileDesc));
  15. } catch (IOException ex) {
  16. throw new RuntimeException(
  17. "Error binding to local socket '" + fileDesc + "'", ex);
  18. }
  19. }
  20. }

代码很简单,再来看下preload()方法

  1. static void preload() {
  2. Log.d(TAG, "begin preload");
  3. preloadClasses();
  4. preloadResources();
  5. preloadOpenGL();
  6. preloadSharedLibraries();
  7. // Ask the WebViewFactory to do any initialization that must run in the zygote process,
  8. // for memory sharing purposes.
  9. WebViewFactory.prepareWebViewInZygote();
  10. Log.d(TAG, "end preload");
  11. }

这其中:
preloadClasses()用于初始化Zygote中需要的class类;
preloadResources()用于初始化系统资源;
preloadOpenGL()用于初始化OpenGL;
preloadSharedLibraries()用于初始化系统libraries;
preloadTextResources()用于初始化文字资源;
prepareWebViewInZygote()用于初始化webview;

我们简单看下preloadClasses()preloadResources()所做的事情

  1. private static void preloadClasses() {
  2. //.......省略代码
  3. is = new FileInputStream(PRELOADED_CLASSES);
  4. // ......省略代码
  5. BufferedReader br
  6. = new BufferedReader(new InputStreamReader(is), 256);
  7.  
  8. int count = 0;
  9. String line;
  10. while ((line = br.readLine()) != null) {
  11. // Skip comments and blank lines.
  12. line = line.trim();
  13. if (line.startsWith("#") || line.equals("")) {
  14. continue;
  15. }
  16.  
  17. try {
  18. if (false) {
  19. Log.v(TAG, "Preloading " + line + "...");
  20. }
  21. Class.forName(line);
  22. if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
  23. if (false) {
  24. Log.v(TAG,
  25. " GC at " + Debug.getGlobalAllocSize());
  26. }
  27. System.gc();
  28. runtime.runFinalizationSync();
  29. Debug.resetGlobalAllocSize();
  30. }
  31. count++;
  32. //......省略代码
  33.  
  34. }
  35.  
  36. //......省略代码
  37. }
  38.  
  39. private static void preloadResources() {
  40. final VMRuntime runtime = VMRuntime.getRuntime();
  41.  
  42. Debug.startAllocCounting();
  43. try {
  44. System.gc();
  45. runtime.runFinalizationSync();
  46. mResources = Resources.getSystem();
  47. mResources.startPreloading();
  48. if (PRELOAD_RESOURCES) {
  49. Log.i(TAG, "Preloading resources...");
  50.  
  51. long startTime = SystemClock.uptimeMillis();
  52. TypedArray ar = mResources.obtainTypedArray(
  53. com.android.internal.R.array.preloaded_drawables);
  54. int N = preloadDrawables(runtime, ar);
  55. ar.recycle();
  56. Log.i(TAG, "...preloaded " + N + " resources in "
  57. + (SystemClock.uptimeMillis()-startTime) + "ms.");
  58.  
  59. startTime = SystemClock.uptimeMillis();
  60. ar = mResources.obtainTypedArray(
  61. com.android.internal.R.array.preloaded_color_state_lists);
  62. N = preloadColorStateLists(runtime, ar);
  63. ar.recycle();
  64. Log.i(TAG, "...preloaded " + N + " resources in "
  65. + (SystemClock.uptimeMillis()-startTime) + "ms.");
  66. }
  67. mResources.finishPreloading();
  68. } catch (RuntimeException e) {
  69. Log.w(TAG, "Failure preloading resources", e);
  70. } finally {
  71. Debug.stopAllocCounting();
  72. }
  73. }

preloadClasses方法所做的事情是从"/system/etc/preloaded-classes"文件种把预加载的类加载到虚拟机中

然后调用startSystemServer(abiList, socket)

  1. private static boolean startSystemServer(String abiList, String socketName)
  2. throws MethodAndArgsCaller, RuntimeException {
  3. long capabilities = posixCapabilitiesAsBits(
  4. OsConstants.CAP_BLOCK_SUSPEND,
  5. OsConstants.CAP_KILL,
  6. OsConstants.CAP_NET_ADMIN,
  7. OsConstants.CAP_NET_BIND_SERVICE,
  8. OsConstants.CAP_NET_BROADCAST,
  9. OsConstants.CAP_NET_RAW,
  10. OsConstants.CAP_SYS_MODULE,
  11. OsConstants.CAP_SYS_NICE,
  12. OsConstants.CAP_SYS_RESOURCE,
  13. OsConstants.CAP_SYS_TIME,
  14. OsConstants.CAP_SYS_TTY_CONFIG
  15. );
  16. /* Hardcoded command line to start the system server */
  17. String args[] = {
  18. "--setuid=1000",
  19. "--setgid=1000",
  20. "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
  21. "--capabilities=" + capabilities + "," + capabilities,
  22. "--nice-name=system_server",
  23. "--runtime-args",
  24. "com.android.server.SystemServer",
  25. };
  26. ZygoteConnection.Arguments parsedArgs = null;
  27.  
  28. int pid;
  29.  
  30. try {
  31. parsedArgs = new ZygoteConnection.Arguments(args);
  32. ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
  33. ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
  34.  
  35. /* Request to fork the system server process */
  36. pid = Zygote.forkSystemServer(
  37. parsedArgs.uid, parsedArgs.gid,
  38. parsedArgs.gids,
  39. parsedArgs.debugFlags,
  40. null,
  41. parsedArgs.permittedCapabilities,
  42. parsedArgs.effectiveCapabilities);
  43. } catch (IllegalArgumentException ex) {
  44. throw new RuntimeException(ex);
  45. }
  46.  
  47. /* For child process */
  48. if (pid == 0) {
  49. if (hasSecondZygote(abiList)) {
  50. waitForSecondaryZygote(socketName);
  51. }
  52.  
  53. handleSystemServerProcess(parsedArgs);
  54. }
  55.  
  56. return true;
  57. }

可以看到这段逻辑的执行逻辑就是通过Zygote fork出SystemServer进程。

在来看runSelectLoop方法

  1. private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
  2. ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
  3. ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
  4. FileDescriptor[] fdArray = new FileDescriptor[4];
  5.  
  6. fds.add(sServerSocket.getFileDescriptor());
  7. peers.add(null);
  8.  
  9. int loopCount = GC_LOOP_COUNT;
  10. while (true) {
  11. int index;
  12.  
  13. /*
  14. * Call gc() before we block in select().
  15. * It's work that has to be done anyway, and it's better
  16. * to avoid making every child do it. It will also
  17. * madvise() any free memory as a side-effect.
  18. *
  19. * Don't call it every time, because walking the entire
  20. * heap is a lot of overhead to free a few hundred bytes.
  21. */
  22. if (loopCount <= 0) {
  23. gc();
  24. loopCount = GC_LOOP_COUNT;
  25. } else {
  26. loopCount--;
  27. }
  28.  
  29. try {
  30. fdArray = fds.toArray(fdArray);
  31. index = selectReadable(fdArray);
  32. } catch (IOException ex) {
  33. throw new RuntimeException("Error in select()", ex);
  34. }
  35.  
  36. if (index < 0) {
  37. throw new RuntimeException("Error in select()");
  38. } else if (index == 0) {
  39. ZygoteConnection newPeer = acceptCommandPeer(abiList);
  40. peers.add(newPeer);
  41. fds.add(newPeer.getFileDescriptor());
  42. } else {
  43. boolean done;
  44. /*开始读取client发出的命令*/
  45. done = peers.get(index).runOnce();
  46.  
  47. if (done) {
  48. peers.remove(index);
  49. fds.remove(index);
  50. }
  51. }
  52. }
  53. }

它所做的事情是:
- 监听client的socket连接
- 发现有连接则建立一个ZygoteConnection对象
- client发送命令,则找到相应的ZygoteConnection对象,并且调用该对象的runOnce方法,来处理client发送的命令
- ZygoteConnection对象处理完毕,则从列表中移除

总结:
Zygote进程mian方法主要执行逻辑:

初始化DDMS;

注册Zygote进程的socket通讯;

初始化Zygote中的各种类,资源文件,OpenGL,类库,Text资源等等;

初始化完成之后fork出SystemServer进程;fork出SystemServer进程之后,关闭socket连接;

 

Android Zygote进程启动分析的更多相关文章

  1. Android 跨进程启动Activity黑屏(白屏)的三种解决方案

    原文链接:http://www.cnblogs.com/feidu/p/8057012.html 当Android跨进程启动Activity时,过程界面很黑屏(白屏)短暂时间(几百毫秒?).当然从桌面 ...

  2. Nginx学习笔记(八) Nginx进程启动分析

    Nginx进程启动分析 worker子进程的执行循环的函数是ngx_worker_process_cycle (src/os/unix/ngx_process_cycle.c). 其中,捕获事件.分发 ...

  3. Android系统启动流程(二)解析Zygote进程启动过程

    1.Zygote简介 在Android系统中,DVM(Dalvik虚拟机).应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器.它通过 ...

  4. Android Zygote进程是如何fork一个APP进程的

    进程创建流程 不管从桌面启动应用还是应用内启动其它应用,如果这个应用所在进程不存在的话,都需要发起进程通过Binder机制告诉system server进程的AMS system server进程的A ...

  5. 【转载】Android App应用启动分析与优化

    前言: 昨晚新版本终于发布了,但是还是记得有测试反馈app启动好长时间也没进入app主页,所以今天准备加个班总结一下App启动那些事! app的启动方式: 1.)冷启动  当启动应用时,后台没有该应用 ...

  6. Android4.4 Framework分析——Zygote进程的启动过程

    Android启动过程中的第一个进程init.在启动过程中会启动两个关键的系统服务进程ServiceManager和Zygote. 本文要介绍的就是Zygote进程的启动,Zygote俗称孵化器,专门 ...

  7. Android 7.0 启动篇 — init原理(二)(转 Android 9.0 分析)

    ========================================================          ================================== ...

  8. Zygote及System进程启动

    1.  init 根据init.rc 运行 app_process, 并携带‘--zygote' 和 ’--startSystemServer' 参数. 2.  AndroidRuntime.cpp: ...

  9. Android应用程序进程启动过程(前篇)

    在此前我讲过Android系统的启动流程,系统启动后,我们就比较关心应用程序是如何启动的,这一篇我们来一起学习Android7.0 应用程序进程启动过程,需要注意的是“应用程序进程启动过程”,而不是应 ...

随机推荐

  1. css总结18:HTML 表单和inut各个常用标签

    1 HTML 表单和输入 1.1 HTML 表单介绍 表单是一个包含表单元素的区域. 表单元素是允许用户在表单中输入内容,比如:文本域(textarea).下拉列表.单选框(radio-buttons ...

  2. Bitmap压缩到指定尺寸大小,获取圆角、圆形图片

    /** * 使用Matrix将Bitmap压缩到指定大小 * @param bitmap * @param w * @param h * @return */ public static Bitmap ...

  3. Sql 查询过慢,尝试重建索引

    DBCC showcontig('Table') DBCC DBREINDEX('Table') 分析表的索引建立情况:DBCC showcontig('Table') DBCC SHOWCONTIG ...

  4. dubbo 安装部署Windows

    1 安装zookeeper 2 安装dubbo    1 下载源码 https://github.com/alibaba/dubbo 2 编译 mvn clean package install -D ...

  5. 死磕Java之聊聊LinkedList源码(基于JDK1.8)

    工作快一年了,近期打算研究一下JDK的源码,也就因此有了死磕java系列 LinkedList 是一个继承于AbstractSequentialList的双向链表,链表不需要capacity的设定,它 ...

  6. Socket 简易静态服务器 WPF MVVM模式(三)

    ViewModels类 这个类其实就是个大杂烩,什么都可以用 这个类没有什么东西,最多的就是写一下xaml页面的逻辑控制,开启关闭监听 using System; using System.Colle ...

  7. select chosen 的入门使用

    首先要引用 因为肯定要引用jq,所以就没有写啦 <link rel="stylesheet" href="__ROOT__/Public/jschy/chosen_ ...

  8. apache-jmeter-3.1的简单压力测试使用方法(下载和安装)

    博客转载https://blog.csdn.net/lan_shu/article/details/55190127 压力测试工具LoadRunner是收费的,而且操作复杂.作为开发人员当然是用apa ...

  9. Python3之configparser模块

    1. 简介 configparser用于配置文件解析,可以解析特定格式的配置文件,多数此类配置文件名格式为XXX.ini,例如mysql的配置文件.在python3.X中 模块名为configpars ...

  10. 【重要的css属性学习】看了乙醇的文章,统计了几个高star前端框架下,Css属性出现最多的,这里学习记录一下

    color background-color display margin-left border-color padding max-width margin-bottom width flex 待 ...