0. 总结:

0.1 相关源码目录:

framework/base/cmds/app_process/app_main.cpp
frameworks/base/core/jni/AndroidRuntime.cpp
frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

0.2 流程总结:

1. init.rc启动进入app_main.cpp
2. app_main.cpp查看init.rc给的相关参数,进行处理进入AndroidRuntime.cpp
3. AndroidRuntime.cpp启动虚拟机,初始化JNI,然后根据函数名通过反射机制加载zygote,进入JAVA层zygote的Zygote.java
4. 注册socket,加载各种资源(类,共享资源,共享库),启动SystemServer服务,循环接收socket,创建新进程

1. native层init.rc(进入zygote)

  1. #名字为zygote的服务,可执行文件路径为/system/bin/app_process,后面几个为带的参数
    #建立socket通讯
    #运行后,只执行一次的几个服务
    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

2. native层的app_main.cpp

/framework/base/cmds/app_process/app_main.cpp

  1.  int main(int argc, char* const argv[]){   //参数argv为:-Xzygote /system/bin --zygote --start-system-server
      if (prctl(PR_SET_NO_NEW_PRIVS, , , , ) < ) {
  2. // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
  3. // EINVAL. Don't die on such kernels.
  4. if (errno != EINVAL) {
  5. LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
  6. return ;
  7. }
  8. }
  9. AppRuntime runtime(argv[], computeArgBlockSize(argc, argv));
  10. // Process command line arguments
  11. // ignore argv[0]
  12. argc--;
  13. argv++;
  14. int i;
  15. for (i = ; i < argc; i++) {
  16. if (argv[i][] != '-') {
  17. break;
  18. }
  19. if (argv[i][] == '-' && argv[i][] == ) {
  20. ++i; // Skip --.
  21. break;
  22. }
  23. runtime.addOption(strdup(argv[i]));
  24. }
  25. // Parse runtime arguments. Stop at first unrecognized option.
  26. bool zygote = false;
  27. bool startSystemServer = false;
  28. bool application = false;
  29. String8 niceName;
  30. String8 className;
  31. ++i; // Skip unused "parent dir" argument.
  32. while (i < argc) { const char* arg = argv[i++];
  33. if (strcmp(arg, "--zygote") == ) {
           //这里我们有
  34. zygote = true;
  35. niceName = ZYGOTE_NICE_NAME;
  36. } else if (strcmp(arg, "--start-system-server") == ) {
  37. startSystemServer = true; //这里我们有
  38. } else if (strcmp(arg, "--application") == ) {
  39. application = true; //这里是进入应用,我们没有
  40. } else if (strncmp(arg, "--nice-name=", ) == ) {
  41. niceName.setTo(arg + ); //没有
  42. } else if (strncmp(arg, "--", ) != break;
  43. } else {
  44. --i;
  45. break;
  46. }
  47. }
  48.   
  49. Vector<String8>if (!className.isEmpty()) {
  50. // We're not in zygote mode, the only argument we need to pass
  51. // to RuntimeInit is the application argument.
  52. //
  53. // The Remainder of args get passed to startup class main(). Make
  54. // copies of them before we overwrite them with the process name.
  55. args.add(application ? String8("application") : String8("tool"));
  56. runtime.setClassNameAndArgs(className, argc - i, argv + i);
  57. } else {
  58. // We're in zygote mode.
  59. maybeCreateDalvikCache();
  60.     //添加所有参数
  61. }
  62. }
  63.  
  64. if (!niceName.isEmpty()) { //没有,不进入
  65. runtime.setArgv0(niceName.string());
  66. set_process_name(niceName.string());
  67. }
  68.  
  69. if (zygote) {
         //进入这里,启动zygote
         //args为:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server
       runtime.start("com.android.internal.os.ZygoteInit", args);
  1. } else if (className) {
  2. runtime.start("com.android.internal.os.RuntimeInit", args);
  3. } else {
  4. fprintf(stderr, "Error: no class name or --zygote supplied.\n");
  5. app_usage();
  6. LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
  7. return ;
  8. }
  9. }

3. native层的AndroidRuntime

frameworks/base/core/jni/AndroidRuntime.cpp

接着往下看:runtime.start

记住,我们传进来的className为:com.android.internal.os.ZygoteInit

参数为options为:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server

  1. void AndroidRuntime::start(const char* className, const Vector<String8>& options)
  2. {
  3. ALOGD(">>>>>> START %s uid %d <<<<<<\n",
  4. className != NULL ? className : "(unknown)", getuid());
  5.  
  6. static const String8 startSystemServer("start-system-server");
  7.  
  8. /*
  9. * 'startSystemServer == true' means runtime is obsolete and not run from
  10. * init.rc anymore, so we print out the boot start event here.
  11. */
  12. for (size_t i = ; i < options.size(); ++i) {
  13. if (options[i] == startSystemServer) {//我们参数有,进入
  14. /* track our progress through the boot sequence */
  15. const int LOG_BOOT_PROGRESS_START = ;
  16. LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
  17. }
  18. }
  19.    //修改环境变量ANDROID_ROOT: /system
  20. const char* rootDir = getenv("ANDROID_ROOT");
  21. if (rootDir == NULL) {
  22. rootDir = "/system";
  23. if (!hasDir("/system")) {
  24. LOG_FATAL("No root directory specified, and /android does not exist.");
  25. return;
  26. }
  27. setenv("ANDROID_ROOT", rootDir, );
  28. }
  29.  
  30. //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
  31. //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
  32.  
  33. /* start the virtual machine */
  34. //启动虚拟机,以后再分析
    JniInvocation jni_invocation;
  35. jni_invocation.Init(NULL);
  36. JNIEnv* env;
  37. if (startVm(&mJavaVM, &env) != ) {
  38. return;
  39. }
  40. onVmCreated(env);
  41.  
  42. /*
  43. * Register android functions.初始化JNI函数
  44. */
  45. if (startReg(env) < ) {
  46. ALOGE("Unable to register all android natives\n");
  47. return;
  48. }
  49.  
  50. /*
  51. * We want to call main() with a String array with arguments in it.
  52. * At present we have two arguments, the class name and an option string.
  53. * Create an array to hold them. 下面都是JNI的用法了,具体去查看JNI那章的博客
  54. */
  55. jclass stringClass;
  56. jobjectArray strArray;
  57. jstring classNameStr;
  58.   /*
      *下面这一串代码就是通过JNI找到ZygoteInit.cpp,然后跳进去,流程是:
      *1.找到String类,然后创建一个String = com.android.internal.os.ZygoteInit(这个变量是className参数传进来的)
      *2.将com.android.internal.os.ZygoteInit转换成com/android/internal/os/ZygoteInit
      *3.查找上面的com/android/internal/os/ZygoteInit这个类中的main函数,
      *4.跳入main中
      */
      stringClass = env->FindClass("java/lang/String");
      assert(stringClass != NULL);
  1. strArray = env->NewObjectArray(options.size() + , stringClass, NULL);
  2. assert(strArray != NULL);
  3. classNameStr = env->NewStringUTF(className);
  4. assert(classNameStr != NULL);
  5. env->SetObjectArrayElement(strArray, , classNameStr);
  6.   
  7. for (size_t i = ; i < options.size(); ++i) {
  8. jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
  9. assert(optionsStr != NULL);
  10. env->SetObjectArrayElement(strArray, i + , optionsStr);
  11. }
  12. /*
  13. * Start VM. This thread becomes the main thread of the VM, and will
  14. * not return until the VM exits.
  15. */
  16. char* slashClassName = toSlashClassName(className);
  17. jclass startClass = env->FindClass(slashClassName);
  18. if (startClass == NULL) {
  19. ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
  20. /* keep going */
  21. } else {
  22. jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
  23. "([Ljava/lang/String;)V");
  24. if (startMeth == NULL) {
  25. ALOGE("JavaVM unable to find main() in '%s'\n", className);
  26. /* keep going */
  27. } else {
           
    //在这里通过反射,正式进入JAVA层的zygote:根据上面的注释,可知这里的startClass为Zygote, startMeth为main
           //strArry为参数:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server(不是很确定,应该是这个)
  28. env->CallStaticVoidMethod(startClass, startMeth, strArray);
  29. #if 0
  30. if (env->ExceptionCheck())
  31. threadExitUncaughtException(env);
  32. #endif
  33. }
  34. }
  35. free(slashClassName);
  36. ALOGD("Shutting down VM\n");
  37. if (mJavaVM->DetachCurrentThread() != JNI_OK)
  38. ALOGW("Warning: unable to detach main thread\n");
  39. if (mJavaVM->DestroyJavaVM() != )
  40. ALOGW("Warning: VM did not shut down cleanly\n");
  41. }

4. JAVA层的Zygote.java

frameworks/base/core/java/com/android/internal/os

ZygoteInit.java函数中的main中

参数如上所分析的argv为:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server

  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()); //--abi-list: 这里有
  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.        //注册zygote的socket,我们socketname为默认的zygote
  25. registerZygoteSocket(socketName);
  26. EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
  27. SystemClock.uptimeMillis());
           //注意:这个很重要,加载各种资源
  28. preload();
  29. EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
  30. SystemClock.uptimeMillis());
  31.  
  32. // Finish profiling the zygote initialization.
  33. SamplingProfilerIntegration.writeZygoteSnapshot();
  34.  
  35. // Do an initial gc to clean up after startup
  36. gc();
  37.  
  38. // Disable tracing so that forked processes do not inherit stale tracing tags from
  39. // Zygote.
  40. Trace.setTracingEnabled(false);
  41.        //在这里启动systemserver
  42. if (startSystemServer) {
  43. startSystemServer(abiList, socketName);
  44. }
  45.  
  46. Log.i(TAG, "Accepting command socket connections");
  47. runSelectLoop(abiList);
  48.  
  49. closeServerSocket();
  50. } catch (MethodAndArgsCaller caller) {
  51. caller.run();
  52. } catch (RuntimeException ex) {
  53. Log.e(TAG, "Zygote died with exception", ex);
  54. closeServerSocket();
  55. throw ex;
  56. }
  57. }

5. JAVA层的preload

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  1. static void preload() {
  2. Log.d(TAG, "begin preload");
  3. preloadClasses(); //加载类
  4. preloadResources(); //加载资源
  5. preloadOpenGL(); //加载OpenGL,这个是跟显示有关的图形库
  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"); //打印log,显示加载完成
  11. }

5.1 加载类preloadClasses

这里用到的反射,忘记了可以看看:语言方面的知识

  1. private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
  1. private static void preloadClasses() {
  2. final VMRuntime runtime = VMRuntime.getRuntime();
  3.  
  4. InputStream is;
  5. try {
  6. is = new FileInputStream(PRELOADED_CLASSES); //在这里面是预加载的类
  7. } catch (FileNotFoundException e) {
  8. Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
  9. return;
  10. }
  11.  
  12. Log.i(TAG, "Preloading classes...");
  13. long startTime = SystemClock.uptimeMillis();
  14.  
  15. // Drop root perms while running static initializers.
  16. setEffectiveGroup(UNPRIVILEGED_GID);
  17. setEffectiveUser(UNPRIVILEGED_UID);
  18.  
  19. // Alter the target heap utilization. With explicit GCs this
  20. // is not likely to have any effect.
  21. float defaultUtilization = runtime.getTargetHeapUtilization();
  22. runtime.setTargetHeapUtilization(0.8f);
  23.  
  24. // Start with a clean slate.
  25. System.gc();
  26. runtime.runFinalizationSync();
  27. Debug.startAllocCounting();
  28.  
  29. try {
  30. BufferedReader br
  31. = new BufferedReader(new InputStreamReader(is), 256);
  32.  
  33. int count = 0;
  34. String line;
  35. while ((line = br.readLine()) != null) { //一行一行的读取出来
  36. // Skip comments and blank lines.
  37. line = line.trim();
  38. if (line.startsWith("#") || line.equals("")) {
  39. continue;
  40. }
  41.  
  42. try {
  43. if (false) {
  44. Log.v(TAG, "Preloading " + line + "...");
  45. }
  46. Class.forName(line); //注意:在这里加载的,是通过类名进行反射
  47. if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
  48. if (false) {
  49. Log.v(TAG,
  50. " GC at " + Debug.getGlobalAllocSize());
  51. }
  52. System.gc();
  53. runtime.runFinalizationSync();
  54. Debug.resetGlobalAllocSize();
  55. }
  56. count++;
  57. } catch (ClassNotFoundException e) {
  58. Log.w(TAG, "Class not found for preloading: " + line);
  59. } catch (UnsatisfiedLinkError e) {
  60. Log.w(TAG, "Problem preloading " + line + ": " + e);
  61. } catch (Throwable t) {
  62. Log.e(TAG, "Error preloading " + line + ".", t);
  63. if (t instanceof Error) {
  64. throw (Error) t;
  65. }
  66. if (t instanceof RuntimeException) {
  67. throw (RuntimeException) t;
  68. }
  69. throw new RuntimeException(t);
  70. }
  71. }
  72.  
  73. Log.i(TAG, "...preloaded " + count + " classes in "
  74. + (SystemClock.uptimeMillis()-startTime) + "ms.");
  75. } catch (IOException e) {
  76. Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
  77. } finally {
  78. IoUtils.closeQuietly(is);
  79. // Restore default.
  80. runtime.setTargetHeapUtilization(defaultUtilization);
  81.  
  82. // Fill in dex caches with classes, fields, and methods brought in by preloading.
  83. runtime.preloadDexCaches();
  84.  
  85. Debug.stopAllocCounting();
  86.  
  87. // Bring back root. We'll need it later.
  88. setEffectiveUser(ROOT_UID);
  89. setEffectiveGroup(ROOT_GID);
  90. }
  91. }

5.2 加载共享资源preloadResources

  1. private static void preloadResources() {
  2. final VMRuntime runtime = VMRuntime.getRuntime();
  3.  
  4. Debug.startAllocCounting();
  5. try {
  6. System.gc();
  7. runtime.runFinalizationSync();
  8. mResources = Resources.getSystem();
  9. mResources.startPreloading();
  10. if (PRELOAD_RESOURCES) {
  11. Log.i(TAG, "Preloading resources...");
  12.  
  13. long startTime = SystemClock.uptimeMillis();
  14. TypedArray ar = mResources.obtainTypedArray(
  15. com.android.internal.R.array.preloaded_drawables);
  16. int N = preloadDrawables(runtime, ar);
  17. ar.recycle();
  18. Log.i(TAG, "...preloaded " + N + " resources in "
  19. + (SystemClock.uptimeMillis()-startTime) + "ms.");
  20.  
  21. startTime = SystemClock.uptimeMillis();
  22. ar = mResources.obtainTypedArray(
  23. com.android.internal.R.array.preloaded_color_state_lists);
  24. N = preloadColorStateLists(runtime, ar);
  25. ar.recycle();
  26. Log.i(TAG, "...preloaded " + N + " resources in "
  27. + (SystemClock.uptimeMillis()-startTime) + "ms.");
  28. }
  29. mResources.finishPreloading();
  30. } catch (RuntimeException e) {
  31. Log.w(TAG, "Failure preloading resources", e);
  32. } finally {
  33. Debug.stopAllocCounting();
  34. }
  35. }

5.3 加载共享库

  1. private static void preloadSharedLibraries() {
  2. Log.i(TAG, "Preloading shared libraries...");
  3. System.loadLibrary("android");
  4. System.loadLibrary("compiler_rt");
  5. System.loadLibrary("jnigraphics");
  6. }

5.4 加载prepareWebViewInZygote(不懂,预留)

6. socket

6.1 registerZygoteSocket

  1. private static void registerZygoteSocket(String socketName) {
  2. if (sServerSocket == null) {
  3. int fileDesc;
  4.        //fullSocketName=ANDROID_SOCKET_zygote,不过,我查了一下我们的代码,没有这个环境变量????不知道为什么
    final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
  1. try {
  2. String env = System.getenv(fullSocketName); //ANDROID_SOCKET_zygote
  3. fileDesc = Integer.parseInt(env);
  4. } catch (RuntimeException ex) {
  5. throw new RuntimeException(fullSocketName + " unset or invalid", ex);
  6. }
  7. try {
              //创建一个socket本地服务的对象,这里的sServerSocket是一个静态属性,我们后面会用到
  8. sServerSocket = new LocalServerSocket(
  9. createFileDescriptor(fileDesc));
  10. } catch (IOException ex) {
  11. throw new RuntimeException(
  12. "Error binding to local socket '" + fileDesc + "'", ex);
  13. }
  14. }
  15. }

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  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); //ANDROID_SOCKET_zygote
  7. fileDesc = Integer.parseInt(env);
  8. } catch (RuntimeException ex) {
  9. throw new RuntimeException(fullSocketName + " unset or invalid", ex);
  10. }
  11.  
  12. try {
             //这里的LocalServerSocket创建了一个对象,然后绑定socket,并listen
             //createFileDescriptor是一个本地函数,通过JNI创建一个文件,并返回fd,如后面所示
  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. }

6.2 com_android_internal_os_ZygoteInit.cpp

frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp

  1. static JNINativeMethod gMethods[] = {
  2. /* name, signature, funcPtr */
  3. { "setreuid", "(II)I",
  4. (void*) com_android_internal_os_ZygoteInit_setreuid },
  5. { "setregid", "(II)I",
  6. (void*) com_android_internal_os_ZygoteInit_setregid },
  7. { "setpgid", "(II)I",
  8. (void *) com_android_internal_os_ZygoteInit_setpgid },
  9. { "getpgid", "(I)I",
  10. (void *) com_android_internal_os_ZygoteInit_getpgid },
  11. { "reopenStdio",
  12. "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
  13. "Ljava/io/FileDescriptor;)V",
  14. (void *) com_android_internal_os_ZygoteInit_reopenStdio},
  15. { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
  16. (void *) com_android_internal_os_ZygoteInit_setCloseOnExec},
  17. { "selectReadable", "([Ljava/io/FileDescriptor;)I",
  18. (void *) com_android_internal_os_ZygoteInit_selectReadable },
  19. { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
  20. (void *) com_android_internal_os_ZygoteInit_createFileDescriptor } /*这里就是上面所调用到的函数*/
  21. };
  1. static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
  2. JNIEnv *env, jobject clazz, jint fd)
  3. {
  4. return jniCreateFileDescriptor(env, fd); //创建文件描述符
  5. }

7. 启动SystemServer

这个函数是调用SystemServer.我就放入SystemServer的博客更合适一点

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  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,1032,3001,3002,3003,3006,3007",
  21. "--capabilities=" + capabilities + "," + capabilities,
  22. "--runtime-init",
  23. "--nice-name=system_server",
  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 */
           //通过fork创建子进程
  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) { //从子进程跳入systemserver
  49. if (hasSecondZygote(abiList)) {
  50. waitForSecondaryZygote(socketName);
  51. }
  52.  
  53. handleSystemServerProcess(parsedArgs);
  54. }
  55.  
  56. return true;
  57. }

8. loop循环接收其他进程,并创建新进程

8.1 runSelectLoop

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

这里用到的socket的select模式,可以查看:Linux知识点

  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.      //拿到fd(也就是我们之前socket创建的),并添加到容器
  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);
              //调用本地函数去select,去监听数组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) {
             //当select到了有可读数据之后,通过accept去监听
             //这里的abiList是之前参数传进来的:--abi-list=armeabi-v71,armeabi
             //新建以后再添加,监听
  39. ZygoteConnection newPeer = acceptCommandPeer(abiList);
  40. peers.add(newPeer);
  41. fds.add(newPeer.getFileDescriptor());
  42. } else {
  43. boolean done;
             //当收到select以后,根据select索引,运行,具体查看章节9
  44. done = peers.get(index).runOnce();
  45.  
  46. if (done) {
  47. peers.remove(index);
  48. fds.remove(index);
  49. }
  50. }
  51. }
  52. }

8.2 com_android_internal_os_ZygoteInit.cpp

frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp

  1. static JNINativeMethod gMethods[] = {
  2. /* name, signature, funcPtr */
  3. { "setreuid", "(II)I",
  4. (void*) com_android_internal_os_ZygoteInit_setreuid },
  5. { "setregid", "(II)I",
  6. (void*) com_android_internal_os_ZygoteInit_setregid },
  7. { "setpgid", "(II)I",
  8. (void *) com_android_internal_os_ZygoteInit_setpgid },
  9. { "getpgid", "(I)I",
  10. (void *) com_android_internal_os_ZygoteInit_getpgid },
  11. { "reopenStdio",
  12. "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
  13. "Ljava/io/FileDescriptor;)V",
  14. (void *) com_android_internal_os_ZygoteInit_reopenStdio},
  15. { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
  16. (void *) com_android_internal_os_ZygoteInit_setCloseOnExec},
  17. { "selectReadable", "([Ljava/io/FileDescriptor;)I",
  18. (void *) com_android_internal_os_ZygoteInit_selectReadable }, //这一个是监听可读
  19. { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
  20. (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
  21. };

在这里关于select的用法和JNI的相关用法可以查看我的博客:

预留。。。

预留。。。

  1. static jint com_android_internal_os_ZygoteInit_selectReadable (
  2. JNIEnv *env, jobject clazz, jobjectArray fds)
  3. {
  4. if (fds == NULL) {
  5. jniThrowNullPointerException(env, "fds == null");
  6. return -;
  7. }
  8.  
  9. jsize length = env->GetArrayLength(fds);
  10. fd_set fdset;
  11.  
  12. if (env->ExceptionOccurred() != NULL) {
  13. return -;
  14. }
  15.  
  16. FD_ZERO(&fdset);
  17.  
  18. int nfds = ;
  19. for (jsize i = ; i < length; i++) {
  20. jobject fdObj = env->GetObjectArrayElement(fds, i);
  21. if (env->ExceptionOccurred() != NULL) {
  22. return -;
  23. }
  24. if (fdObj == NULL) {
  25. continue;
  26. }
  27. int fd = jniGetFDFromFileDescriptor(env, fdObj);
  28. if (env->ExceptionOccurred() != NULL) {
  29. return -;
  30. }
  31.  
  32. FD_SET(fd, &fdset);
  33.  
  34. if (fd >= nfds) {
  35. nfds = fd + ;
  36. }
  37. }
  38.  
  39. int err;
  40. do {
  41. err = select (nfds, &fdset, NULL, NULL, NULL); //在这里监听
  42. } while (err < && errno == EINTR);
  43.  
  44. if (err < ) {
  45. jniThrowIOException(env, errno);
  46. return -;
  47. }
  48.  
  49. for (jsize i = ; i < length; i++) {
  50. jobject fdObj = env->GetObjectArrayElement(fds, i);
  51. if (env->ExceptionOccurred() != NULL) {
  52. return -;
  53. }
  54. if (fdObj == NULL) {
  55. continue;
  56. }
  57. int fd = jniGetFDFromFileDescriptor(env, fdObj);
  58. if (env->ExceptionOccurred() != NULL) {
  59. return -;
  60. }
  61. if (FD_ISSET(fd, &fdset)) {
  62. return (jint)i;
  63. }
  64. }
  65. return -;
  66. }

9. runOnce启动新进程(没有看的很懂,之后再分析)

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

从之前的

  1. done = peers.get(index).runOnce();

然后查看peers类型

  1. ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

搜索ZygoteConnection可以找到

  1. boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
  2.  
  3. String args[];
  4. Arguments parsedArgs = null;
  5. FileDescriptor[] descriptors;
  6.  
  7. long startTime = SystemClock.elapsedRealtime();
  8.  
  9. try {
  10. args = readArgumentList();
  11. descriptors = mSocket.getAncillaryFileDescriptors();
  12. } catch (IOException ex) {
  13. Log.w(TAG, "IOException on command socket " + ex.getMessage());
  14. closeSocket();
  15. return true;
  16. }
  17.  
  18. checkTime(startTime, "zygoteConnection.runOnce: readArgumentList");
  19. if (args == null) {
  20. // EOF reached.
  21. closeSocket();
  22. return true;
  23. }
  24.  
  25. /** the stderr of the most recent request, if avail */
  26. PrintStream newStderr = null;
  27.  
  28. if (descriptors != null && descriptors.length >= 3) {
  29. newStderr = new PrintStream(
  30. new FileOutputStream(descriptors[2]));
  31. }
  32.  
  33. int pid = -1;
  34. FileDescriptor childPipeFd = null;
  35. FileDescriptor serverPipeFd = null;
  36.  
  37. try {
  38. parsedArgs = new Arguments(args);
  39.  
  40. if (parsedArgs.abiListQuery) {
  41. return handleAbiListQuery();
  42. }
  43.  
  44. if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
  45. throw new ZygoteSecurityException("Client may not specify capabilities: " +
  46. "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
  47. ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
  48. }
  49.  
  50. applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  51. applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  52. applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  53. applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  54.  
  55. checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
  56.  
  57. applyDebuggerSystemProperty(parsedArgs);
  58. applyInvokeWithSystemProperty(parsedArgs);
  59.  
  60. checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
  61.  
  62. int[][] rlimits = null;
  63.  
  64. if (parsedArgs.rlimits != null) {
  65. rlimits = parsedArgs.rlimits.toArray(intArray2d);
  66. }
  67.  
  68. if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
  69. FileDescriptor[] pipeFds = Os.pipe();
  70. childPipeFd = pipeFds[1];
  71. serverPipeFd = pipeFds[0];
  72. ZygoteInit.setCloseOnExec(serverPipeFd, true);
  73. }
  74.  
  75. /**
  76. * In order to avoid leaking descriptors to the Zygote child,
  77. * the native code must close the two Zygote socket descriptors
  78. * in the child process before it switches from Zygote-root to
  79. * the UID and privileges of the application being launched.
  80. *
  81. * In order to avoid "bad file descriptor" errors when the
  82. * two LocalSocket objects are closed, the Posix file
  83. * descriptors are released via a dup2() call which closes
  84. * the socket and substitutes an open descriptor to /dev/null.
  85. */
  86.  
  87. int [] fdsToClose = { -1, -1 };
  88.  
  89. FileDescriptor fd = mSocket.getFileDescriptor();
  90.  
  91. if (fd != null) {
  92. fdsToClose[0] = fd.getInt$();
  93. }
  94.  
  95. fd = ZygoteInit.getServerSocketFileDescriptor();
  96.  
  97. if (fd != null) {
  98. fdsToClose[1] = fd.getInt$();
  99. }
  100.  
  101. fd = null;
  102.  
  103. checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
  104. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
  105. parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
  106. parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
  107. parsedArgs.appDataDir);
  108. checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
  109. } catch (IOException ex) {
  110. logAndPrintError(newStderr, "Exception creating pipe", ex);
  111. } catch (ErrnoException ex) {
  112. logAndPrintError(newStderr, "Exception creating pipe", ex);
  113. } catch (IllegalArgumentException ex) {
  114. logAndPrintError(newStderr, "Invalid zygote arguments", ex);
  115. } catch (ZygoteSecurityException ex) {
  116. logAndPrintError(newStderr,
  117. "Zygote security policy prevents request: ", ex);
  118. }
  119.  
  120. try {
  121. if (pid == 0) {
  122. // in child
  123. IoUtils.closeQuietly(serverPipeFd);
  124. serverPipeFd = null;
  125. handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
  126.  
  127. // should never get here, the child is expected to either
  128. // throw ZygoteInit.MethodAndArgsCaller or exec().
  129. return true;
  130. } else {
  131. // in parent...pid of < 0 means failure
  132. IoUtils.closeQuietly(childPipeFd);
  133. childPipeFd = null;
  134. return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
  135. }
  136. } finally {
  137. IoUtils.closeQuietly(childPipeFd);
  138. IoUtils.closeQuietly(serverPipeFd);
  139. }
  140. }

i.mx6 Android5.1.1 Zygote的更多相关文章

  1. i.mx6 Android5.1.1 初始化流程之init.rc解析(未完成)

    接上一篇:i.mx6 Android5.1.1 初始化流程之init进程 参考资料:http://blog.csdn.net/mr_raptor/article/category/799879 这个博 ...

  2. i.mx6 Android5.1.1 System server

    1. 概述: 1. Zygote进程是Android Java世界的开创者,所有的Java应用程序进程都由Zygote进程创建: 2. Zygote创建应用程序进程过程其实就是复制自身进程地址空间作为 ...

  3. i.mx6 Android5.1.1 初始化流程之框架

    Android启动过程分为以下几个步骤: 1.  Boot ROM:  上电后启动芯片固话代码. 2.  BootLoader:固话代码会根据启动模式启动bootloader,(一般为启动引脚的电平的 ...

  4. i.mx6 Android5.1.1 servicemanager本地服务

    接在之前的 i.mx6 Android5.1.1 初始化流程之init进程 i.mx6 Android5.1.1 初始化流程之init.rc解析 servicemanager是由init创建的本地服务 ...

  5. i.mx6 Android5.1.1 初始化流程之init进程(未完成)

    概述: 接在i.mx6 Android5.1.1 初始化流程之框架之后 参考资料:http://blog.csdn.net/mr_raptor/article/category/799879 相关源码 ...

  6. i.mx6 Android5.1.1 系统属性

    属性变更的请求时init事件循环处理的另一个事件,在Android平台中,为了让运行中的所有进程共享系统运行时所需要的各种设置值,系统开辟了属性存储区域,并提供了访问该区域的API.属性由键(key) ...

  7. i.mx6 Android5.1.1 build解析

    参考资料:理解 Android Build 系统 把总结放前面: 1. 常用编译命令 make clean 执行清理,等同于:rm -rf out/. make sdk 编译出 Android 的 S ...

  8. i.mx6 Android5.1.1 vibrator系统服务流程

    0. 概述 0.1 小结 下面来从APP一直分析到kernel的driver,因为vibrator是我所知的最简单的系统服务,分析过程过来,可以获取整个安卓服务的运行思路,把相关知识点都串联起来,又不 ...

  9. imx6 Android6.0.1 init.rc解析

    1. 概述 1.1 概述 之前分析过android5的init.rc,不过还是不够仔细,现在来看看android6的,多的就不写了,只写关键点 忘记一些基本概念可以先看看之前的笔记: Android5 ...

随机推荐

  1. 2:C#TPL探秘

    理论: 1. 只要方法是 Task类型的返回值,都可以用 await 来等待调用获取返回值. 2. 如果一个返回 Task类型的方法被标记了 async,那么只要方法内部直接 return T 这个 ...

  2. [uwp]ImageSource和byte[]相互转换

    最近做一个小app遇到一个问题,到目前还没有比较好的解决方法(可能是我查的资料不够多) 需求如下: 1.把一个Image中的图像保存到字节数组: 2.把字节数组转换为ImageSource,通过Ima ...

  3. 如何在WS系统的DOS命令台打印JAVA_HOME变量

    echo %JAVA_HOME% 查看环境变量 path 新增临时环境变量 path D:\test;%path% 注意是反斜杆 cls 清空 F7 显示历史CMD指令

  4. TPshop商城 Getshell后门文件分析与复现

    本文作者:i春秋签约作家——Laimooc 官网地址:http://www.tp-shop.cn/ 影响版本:TPSHOP v2.0.0 后门文件:eval-stdin.php 内容: <?ph ...

  5. java后台简单从腾讯云下载文件通知前端以附件的形式保存

    腾讯云对象存储和阿里云差不多 这是我的配置 /** * 腾讯云client * @return COSClient */ public static COSClient getCOSClient() ...

  6. Ambiguous mapping found. Cannot map 'XXXController' bean method

    springMVC报错,原因方法之间@RequestMapping()到了同一个地址,导致springmvc无法定位

  7. QuantLib 金融计算——数学工具之求解器

    目录 QuantLib 金融计算--数学工具之求解器 概述 调用方式 非 Newton 算法(不需要导数) Newton 算法(需要导数) 如果未做特别说明,文中的程序都是 Python3 代码. Q ...

  8. 为项目配置了Bean,结果Spring Boot并没有扫描到

    问题如图,而这个问题遇见的场景是因为自己在一个基础项目里面配置cros,按照网上的说法都配置了一边,结果发现前后端的通讯仍然报跨域问题.后来怀疑是否bean并没有被注入进去,导致没有生效,于是在代码中 ...

  9. Vue 不睡觉教程3 - 来点实在的:自动计算剩余时间的任务列表

    目标前两课教的是入门和文件结构.都没有什么实在的东西.这次我们要来点实在的.我们要做出一个待办列表.这个待办列表有以下特点: 可以自动从文本中抽取出这件事情的开始时间可以显示当前距离这件事情的开始时间 ...

  10. Django分页类的封装

    Django分页类的封装 Django ORM  封装 之前有提到(Django分页的实现)会多次用到分页,将分页功能封装起来能极大提高效率. 其实不是很难,就是将之前实现的代码全都放到类中,将需要用 ...