服务器之家

服务器之家 > 正文

详细分析Android中实现Zygote的源码

时间:2021-03-04 10:46     来源/作者:低调小一

概述

Android系统中,所有的应用程序进程,以及用来运行系统关键服务的System进程都是由zygote进程负责创建的。因此,我们将它称为进程孵化器。zygote进程是通过复制自身的方式来创建System进程和应用程序进程的。由于zygote进程在启动时会在内部创建一个虚拟机实例,因此,通过复制zygote进程而得到的System进程和应用程序进程可以快速地在内部获得一个虚拟机实例拷贝。
zygote进程在启动完成之后,会马上将System进程启动起来,以便它可以将系统的关键服务启动起来。下面我们将介绍zygote进程的启动脚本,然后分析它和System进程的启动过程。
zygote分析

zygote进程的启动脚本如下:

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


在我之前的一篇博客中已经分析了init进程是如何启动service服务了,需要了解的同学可以参考这篇文章:Android init进程——解析配置文件

通过zygote服务的启动脚本,我们可以知道,zygote进程的实际是二进制文件app_process的调用,我们就从这个应用程序的main函数入手去分析一下zygote进程的启动过程,源码如下(/frameworks/base/cmds/app_process/app_main.cpp):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
 * 将-Xzygote加入到JavaVMOption中,返回/system/bin参数指向的下标
 */
int AndroidRuntime::addVmArguments(int argc, const char* const argv[])
{
  int i;
 
  for (i = 0; i < argc; i ++) {
    if (argv[i][0] != '-') {
      return i;
    }
    if (argv[i][1] == '-' && argv[i][2] == 0) {
      return i + 1;
    }
 
    JavaVMOption opt;
    memset(&opt, 0, sizeof(opt));
    opt.optionString = (char*)argv[i];
    mOptions.add(opt);
  }
  return i;
}
 
int main(int argc, char* const argv[])
{
  // zygote call parameters
  // /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
 
  // These are global variables in ProcessState.cpp
  mArgC = argc;
  mArgV = argv;
 
  mArgLen = 0;
  for (int i = 0; i < argc; i ++) {
    mArgLen += strlen(argv[i]) + 1;
  }
  // 去除末尾的空格
  mArgLen--;
 
  AppRuntime runtime;
  const char* argv0 = argv[0];
 
  // Process command line arguments
  // ignore argv[0]
  argc --;
  argv ++;
 
  // Everything up tp '--' or first non '-' arg goes to the vm
  int i = runtime.addVmArguments(argc, argv);
 
  // Parse runtime arguments. Stop at first unrecognized option.
  bool zygote = false;
  bool startSystemServer = false;
  bool application = false;
  const char* parentDir = NULL;
  const char* niceName = NULL;
  const char* className = NULL;
  while (i < argc) {
    const char* arg = argv[i ++];
    if (!parentDir) {
      parentDir = arg;
    } else if (strcmp(arg, "--zygote") == 0) {
      zygote = true;
      niceName = "zygote";
    } else if (strcmp(arg, "--start-system-server") == 0) {
      startSystemServer = true;
    } else if (strcmp(arg, "--application") == 0) {
      application = true;
    } else if (strncmp(arg, "--nice-name=", 12)) {
      niceName = arg + 12;
    } else {
      className = arg;
      break;
    }
  }
 
  if (niceName && *niceName) {
    setArgv0(argv0, niceName);
    set_process_name(niceName);
  }
 
  runtime.mParentDir = parentDir;
 
  if (zygote) {
    // 进入到AppRuntime的start函数
    runtime.start("com.android.internal.os.ZygoteInit",
      startSystemServer? "start-system-server" : "");
  } else if (className) {
    runtime.mClassName = className;
    runtime.mArgc = argc - i;
    runtime.mArgv = argv + i;
    runtime.start("com.android.internal.os.RuntimeInit", application ? "application" : "tool");
  } else {
    fprintf("stderr", "Error: no class name or --zygote supplied.\n");
    app_usage();
    LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied");
    return 10;
  }
}


在zygote的main函数中,通过AppRuntime runtime代码创建了一个AppRuntime对象runtime,接下来Zygote进程就是通过它来进一步启动的。
init.rc中关于启动zygote命令中包含了–zygote参数,所以在if(strcmp(arg, “–zygote”) == 0)判断的时候,会将niceName赋值为”zygote”,然后通过set_process_name(niceName)函数将当前进程的名称设置为zygote。这也是为什么调用的脚本为/system/bin/app_process,而进程名为zygote的原因。set_process_name函数的源码如下(/system/core/libcutils/process_name.c):

?
1
2
3
4
5
6
7
8
9
10
11
12
static const char* process_name = "unknown";
void set_process_name(const char* new_name)
{
  if (new_name == NULL) {
    return;
  }
 
  int len = strlen(new_name);
  char* copy = (char*)malloc(len + 1);
  strcpy(copy, new_name);
  process_name = (const char*) copy;
}

从init.rc文件中关于zygote进程的配置参数可知,Zygote进程传递给应用程序app_process的启动参数arg还包含一个”–start-system-server”选项。因此,在调用AppRuntime对象runtime的成员函数start时,第二个参数为”start-system-server”,表示zygote进程启动完成之后,需要将system进程启动起来。
AppRuntime分析

AppRuntime类的成员函数start是从父类AndroidRuntime继承下来的,因此,接下来我们就继续分析AndroidRuntime类的成员函数start的实现,函数源码位置:/frameworks/base/core/jni/AndroidRuntime.cpp:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
char* AndroidRuntime::toSlashClassName(const char* className)
{
  char* result = strdup(className);
  for (char* cp = result; *cp != '\0'; cp ++) {
    if (*cp == '.') {
      *cp = '/';
    }
  }
 
  return result;
}
 
/**
 * Start the Android runtime. This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method int the class
 * named by "className".
 *
 * 这两个参数的值分别为:
 * const char* className = "com.android.internal.os.ZygoteInit";
 * const char* options = "start-system-server";
 */
void AndroidRuntime::start(const char* className, const char* options)
{
  ALOGD("\n>>>>> AndroidRuntime START %s <<<<<<\n",
    className != NULL ? className : "(unknown)");
 
  /**
   * 'startSystemServer == true' means runtime is obsolete and not run from
   * init.rc anymore, so we print out the boot start event here.
   */
  if (strcmp(options, "start-system-server") == 0) {
    const int LOG_BOOT_PROGRESS_START = 3000;
    LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
  }
 
  // 设置ANDROID_ROOT环境变量
  const char* rootDir = getenv("ANDROID_ROOT");
  if (rootDir == NULL) {
    rootDir = "/system";
    if (!hasDir("/system")) {
      LOG_FATAL("No root directory specified, and /android dose not exist.");
      return;
    }
    setenv("ANDROID_ROOT", rootDir, 1);
  }
 
 
  JniInvocation jni_invocation;
  jni_invocation.Init(NULL);
  JNIEnv* env;
  // 1. 创建虚拟机
  if (startVm(&mJavaVM, &env) != 0) {
    return;
  }
  onVmCreated(env);
 
  // 2. 注册JNI函数
  if (startReg(env) < 0) {
    ALOGE("Unable to register all android natives\n");
    return;
  }
 
  jclass stringClass;
  jobjectArray strArray;
  jstring classNameStr;
  jstring optionsStr;
 
  stringClass = env->FindClass("java/lang/String");
  assert(stringClass != NULL);
  // 创建一个有两个元素的String数组,用Java代码表示为:String[] strArray = new String[2];
  strArray = env->NewObjectArray(2, stringClass, NULL);
  assert(strArray != NULL);
  classNameStr = env->NewStringUTF(className);
  assert(classNameStr != NULL);
  // 设置第一个元素为"com.android.internal.os.ZygoteInit"
  env->SetObjectArrayElement(strArray, 0, classNameStr);
  optionsStr = env->NewStringUTF(options);
  // 设置第二个元素为"start-system-server"
  env->SetObjectArrayElement(strArray, 1, optionsStr);
 
  // 将字符串"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"
  char* slashClassName = toSlashClassName(className);
  jclass startClass = env->FindClass(slashClassName);
  if (startClass == NULL) {
    ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
  } else {
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
    if (startMeth == NULL) {
      ALOGE("JavaVM unable to find main() in '%s\n'", className);
    } else {
      // 3.
      // 通过JNI调用java函数,注意调用的是main函数,所属的类是"com.android.internal.os.ZygoteInit".
      // 传递的参数是"com.android.internal.os.ZygoteInit true"
      env->CallStaticVoidMethod(startClass, startMeth, strArray);
    }
  }
  free(slashClassName);
 
  ALOGD("Shutting down VM\n");
  if (mJavaVM->DetachCurrentThread() != JNI_OK) {
    ALOGW("Warning: unable to detach main thread\n");
  }
  if (mJavaVM->DestoryJavaVM() != 0) {
    ALOGW("Warning: VM did not shut down cleanly\n");
  }
}

 

上述代码有几处关键点,分别是:

  1.     创建虚拟机。
  2.     注册JNI函数。
  3.     进入Java世界。

接下来,我们分别分析这三个关键点。
创建虚拟机——startVm

startVm并没有特别之处,就是调用JNI的虚拟机创建函数,但是创建虚拟机时的一些参数却是在startVm中确定的,其源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#define PROPERTY_VALUE_MAX 92
/**
 * Start the Dalvik Virtual Machine.
 *
 * Various arguments, most determined by system properties, are passed in.
 * The "mOptions" vector is updated.
 *
 * Returns 0 on success.
 */
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIENV** pEnv)
{
  int result = -1;
  JavaVMInitArgs initArgs;
  JavaVMOption opt;
  char propBuf[PROPERTY_VALUE_MAX];
  char stackTraceFileBuf[PROPERTY_VALUE_MAX];
  char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
  char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
  char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
  char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
  char heapsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
  char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
  char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
  char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
  char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
  char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
  char extraOptsBuf[PROPERTY_VALUE_MAX];
  char* stackTraceFile = NULL;
  bool checkJni = false;
  bool checkDexSum = false;
  bool logStdio = false;
  enum {
    KEMDefault,
    KEMIntPortable,
    KEMIntFast,
    KEMJitCompiler,
  } executionMode = KEMDefault;
 
  /**
   * 这段代码是用了设置JNI_check选项的。JNI_check指的是Native层调用JNI函数时,系统所做的一些检查动作。
   * 这个选项虽然能增加可靠性,但是还有一些副作用:
   * 1. 因为检查工作比较耗时,所以会影响系统运行速度。
   * 2. 有些检查工作比较耗时,一旦出错,整个进程会abort。
   * 所以,JNI_check选项一般只在eng版本设置。
   */
  property_get("dalvik.vm.checkjni", propBuf, "");
  if (strcmp(propBuf, "true") == 0) {
    checkJni = true;
  } else if (strcmp(propBuf, "false") != 0) {
    property_get("ro.kernel.android.checkjni", propBuf, "");
    if (propBuf[0] == '1') {
      checkJni = true;
    }
  }
 
  property_get("dalvik.vm.execution-mode", propBuf, "");
  if (strcmp(propBuf, "int:portable") == 0) {
    executionMode = KEMIntPortable;
  } else if (strcmp(propBuf, "int:fast") == 0) {
    executionMode = KEMIntFast; 
  } else if (strcmp(propBuf, "int:jit") == 0) {
    executionMode = KEMJitCompiler;
  }
 
  // ... 省略大部分参数设置
 
  /**
   * 设置虚拟机的heapsize,默认为16m。绝大多数厂商都会在build.prop文件里修改这个属性,一般是256m。
   * heapsize不能设置得过小,否则在操作大尺寸的图片时无法分配所需的内存。
   */
  strcpy(heapsizeOptsBuf, "-Xmx");
  property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
  opt.optionString = heapsizeOptsBuf;
  mOptions.add(opt);
 
  // ......
 
  if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
    ALOGE("JNI_CreateJavaVM failed\n");
    goto bail;
  }
 
  result = 0;
 
bail:
  free(stackTraceFile);
  return result;
}


更多虚拟机参数的设置,我这里就不做特殊说明了,大家感兴趣可以自行google。(ps:因为我不太懂虚拟机这一块…)
注册JNI函数——startReg

上面讲了如何创建虚拟机,接下来需要给这个虚拟机注册一些JNI函数。正是因为后续的Java世界用到的一些函数是采用native方式实现的,所以才必须提前注册这些函数。

接下来,我们来看一下startReg函数的源码实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int AndroidRuntime::startReg(JNIEnv* env)
{
  // 设置Thread类的线程创建函数为javaCreateThreadEtc
  androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
 
  ALOGV("--- registering native functions ---\n");
 
  env->PushLocalFrame(200);
 
  if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
    env->PopLocalFrame(NULL);
    return -1;
  }
  env->PopLocalFrame(NULL);
 
  return 0;
}


关键是需要注册JNI函数,具体实现是由register_jni_procs函数实现的,我们来看一下这个函数的具体实现(/frameworks/base/core/jni/AndroidRuntime.cpp):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
static int register_jni_procs(const RegJNIRec array[], size_T count, JNIEnv* env)
{
  for (size_t i = 0; i < count; i ++) {
    if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
      ALOGD("------!!! %s failed to load\n", array[i].mName);
#endif
      return -1;
    }
  }
 
  return 0;
}


通过源码,我们可以看到,register_jni_procs只是对array数组的mProc函数的封装,而array数组指向的是gRegJNI数组,我们来看一下这个数组的实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
static const RegJNIRec gRegJNI[] = {
  REG_JNI(register_android_debug_JNITest),
  REG_JNI(register_com_android_internal_os_RuntimeInit),
  REG_JNI(register_android_os_SystemClock),
  REG_JNI(register_android_util_EventLog),
  REG_JNI(register_android_util_Log),
  REG_JNI(register_android_util_FloatMath),
  REG_JNI(register_android_text_format_Time),
  REG_JNI(register_android_content_AssetManager),
  REG_JNI(register_android_content_StringBlock),
  REG_JNI(register_android_content_XmlBlock),
  REG_JNI(register_android_emoji_EmojiFactory),
  REG_JNI(register_android_text_AndroidCharacter),
  REG_JNI(register_android_text_AndroidBidi),
  REG_JNI(register_android_view_InputDevice),
  REG_JNI(register_android_view_KeyCharacterMap),
  REG_JNI(register_android_os_Process),
  REG_JNI(register_android_os_SystemProperties),
  REG_JNI(register_android_os_Binder),
  REG_JNI(register_android_os_Parcel),
  REG_JNI(register_android_view_DisplayEventReceiver),
  REG_JNI(register_android_nio_utils),
  REG_JNI(register_android_graphics_Graphics),
  REG_JNI(register_android_view_GraphicBuffer),
  REG_JNI(register_android_view_GLES20DisplayList),
  REG_JNI(register_android_view_GLES20Canvas),
  REG_JNI(register_android_view_HardwareRenderer),
  REG_JNI(register_android_view_Surface),
  REG_JNI(register_android_view_SurfaceControl),
  REG_JNI(register_android_view_SurfaceSession),
  REG_JNI(register_android_view_TextureView),
  REG_JNI(register_com_google_android_gles_jni_EGLImpl),
  REG_JNI(register_com_google_android_gles_jni_GLImpl),
  REG_JNI(register_android_opengl_jni_EGL14),
  REG_JNI(register_android_opengl_jni_EGLExt),
  REG_JNI(register_android_opengl_jni_GLES10),
  REG_JNI(register_android_opengl_jni_GLES10Ext),
  REG_JNI(register_android_opengl_jni_GLES11),
  REG_JNI(register_android_opengl_jni_GLES11Ext),
  REG_JNI(register_android_opengl_jni_GLES20),
  REG_JNI(register_android_opengl_jni_GLES30),
 
  REG_JNI(register_android_graphics_Bitmap),
  REG_JNI(register_android_graphics_BitmapFactory),
  REG_JNI(register_android_graphics_BitmapRegionDecoder),
  REG_JNI(register_android_graphics_Camera),
  REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),
  REG_JNI(register_android_graphics_Canvas),
  REG_JNI(register_android_graphics_ColorFilter),
  REG_JNI(register_android_graphics_DrawFilter),
  REG_JNI(register_android_graphics_Interpolator),
  REG_JNI(register_android_graphics_LayerRasterizer),
  REG_JNI(register_android_graphics_MaskFilter),
  REG_JNI(register_android_graphics_Matrix),
  REG_JNI(register_android_graphics_Movie),
  REG_JNI(register_android_graphics_NinePatch),
  REG_JNI(register_android_graphics_Paint),
  REG_JNI(register_android_graphics_Path),
  REG_JNI(register_android_graphics_PathMeasure),
  REG_JNI(register_android_graphics_PathEffect),
  REG_JNI(register_android_graphics_Picture),
  REG_JNI(register_android_graphics_PorterDuff),
  REG_JNI(register_android_graphics_Rasterizer),
  REG_JNI(register_android_graphics_Region),
  REG_JNI(register_android_graphics_Shader),
  REG_JNI(register_android_graphics_SurfaceTexture),
  REG_JNI(register_android_graphics_Typeface),
  REG_JNI(register_android_graphics_Xfermode),
  REG_JNI(register_android_graphics_YuvImage),
  REG_JNI(register_android_graphics_pdf_PdfDocument),
 
  REG_JNI(register_android_database_CursorWindow),
  REG_JNI(register_android_database_SQLiteConnection),
  REG_JNI(register_android_database_SQLiteGlobal),
  REG_JNI(register_android_database_SQLiteDebug),
  REG_JNI(register_android_os_Debug),
  REG_JNI(register_android_os_FileObserver),
  REG_JNI(register_android_os_MessageQueue),
  REG_JNI(register_android_os_SELinux),
  REG_JNI(register_android_os_Trace),
  REG_JNI(register_android_os_UEventObserver),
  REG_JNI(register_android_net_LocalSocketImpl),
  REG_JNI(register_android_net_NetworkUtils),
  REG_JNI(register_android_net_TrafficStats),
  REG_JNI(register_android_net_wifi_WifiNative),
  REG_JNI(register_android_os_MemoryFile),
  REG_JNI(register_com_android_internal_os_ZygoteInit),
  REG_JNI(register_android_hardware_Camera),
  REG_JNI(register_android_hardware_camera2_CameraMetadata),
  REG_JNI(register_android_hardware_SensorManager),
  REG_JNI(register_android_hardware_SerialPort),
  REG_JNI(register_android_hardware_UsbDevice),
  REG_JNI(register_android_hardware_UsbDeviceConnection),
  REG_JNI(register_android_hardware_UsbRequest),
  REG_JNI(register_android_media_AudioRecord),
  REG_JNI(register_android_media_AudioSystem),
  REG_JNI(register_android_media_AudioTrack),
  REG_JNI(register_android_media_JetPlayer),
  REG_JNI(register_android_media_RemoteDisplay),
  REG_JNI(register_android_media_ToneGenerator),
 
  REG_JNI(register_android_opengl_classes),
  REG_JNI(register_android_server_NetworkManagementSocketTagger),
  REG_JNI(register_android_server_Watchdog),
  REG_JNI(register_android_ddm_DdmHandleNativeHeap),
  REG_JNI(register_android_backup_BackupDataInput),
  REG_JNI(register_android_backup_BackupDataOutput),
  REG_JNI(register_android_backup_FileBackupHelperBase),
  REG_JNI(register_android_backup_BackupHelperDispatcher),
  REG_JNI(register_android_app_backup_FullBackup),
  REG_JNI(register_android_app_ActivityThread),
  REG_JNI(register_android_app_NativeActivity),
  REG_JNI(register_android_view_InputChannel),
  REG_JNI(register_android_view_InputEventReceiver),
  REG_JNI(register_android_view_InputEventSender),
  REG_JNI(register_android_view_InputQueue),
  REG_JNI(register_android_view_KeyEvent),
  REG_JNI(register_android_view_MotionEvent),
  REG_JNI(register_android_view_PointerIcon),
  REG_JNI(register_android_view_VelocityTracker),
 
  REG_JNI(register_android_content_res_ObbScanner),
  REG_JNI(register_android_content_res_Configuration),
 
  REG_JNI(register_android_animation_PropertyValuesHolder),
  REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
  REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
};
 
#ifdef NDEBUG
  #define REG_JNI(name) {name}
  struct RegJNIRec {
    int (*mProc)(JNIEnv*);
  };
#else
  #define REG_JNI(name) {name, #name}
  struct RegJNIRec {
    int (*mProc)(JNIEnv*);
    const char* mName;
  };
#endif


可以看到,REG_JNI是一个宏,宏里面包括的就是那个参数为JNIEnv*,返回值为int的函数指针mProc,我们以register_android_debug_JNITest为例,源码位置为/frameworks/base/core/jni/android_debug_JNITest.cpp:

?
1
2
3
4
5
6
#define NELEM(x) (sizeof(x)/sizeof(*(x)))
 
int register_android_debug_JNITest(JNIEnv* env)
{
  return jniRegisterNativeMethods(env, "android/debug/JNITest", gMethods, NELEM(gMethods));
}


可以看到,mProc其实就是为Java类注册JNI函数。
进入JAVA世界

可以看到CallStaticVoidMethod最终将调用com.android.internal.os.ZygoteInit的main函数,下面就来看一下这个Java世界的入口函数。源码位置:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java,源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public static void main(String argv[])
{
  try {
    SamplingProfilerIntegration.start();
 
    // 1. 注册zygote用的socket
    registerZygoteSocket();
    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
 
    // 2. 预加载类和资源
    preload();
    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis());
 
    SamplingProfilerIntegration.writeZygoteSnapshot();
 
    // 强制执行一次垃圾收集
    gc();
 
    Trace.setTracingEnabled(false);
 
    if (argv.length != 2) {
      throw new RuntimeException(argv[0] + USAGE_STRING);
    }
 
    if (argv[1].equals("start-system-server")) {
      // 3. 启动system-server
      startSystemServer();
    } else if (!argv[1].equals("")) {
      throw new RuntimeException(argv[0] + USAGE_STRING);
    }
 
    Log.i(TAG, "Accepting command socket connections");
 
    // 4. 进入请求应答模式
    runSelectLoop();
    closeServerSocket();
 
  } catch(MethodAndArgsCaller caller) {
    caller.run();
  } catch(RuntimeException ex) {
    Log.e(TAG, "Zygote died with exception", ex);
    closeServerSocket();
    throw ex;
  }
}

 

上述代码中有5个重要的点,我已经通过标号标记出来了,接下来我们分别分析一下这5点函数的具体实现。
建立IPC通信服务端——registerZygoteSocket

zygote及系统中其他程序的通信没有使用Binder,而是采用了基于AF_UNIX类型的socket。registerZygoteSocket函数的使命正是建立这个Socket,实现代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private static void registerZygoteSocket()
{
  if (sServerSocket == null) {
    int fileDesc;
    try {
      String env = System.getenv(ANDROID_SOCKET_ENV);
      fileDesc = Integer.parseInt(env);
    } catch (RuntimeException ex) {
      throw new RuntimeException(ANDROID_SOCKET_ENV + " unset or invalid", ex);
    }
 
    try
      sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));
    } catch(IOException ex) { 
      throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
    }
  }
}
 
public class LocalServerSocket {
  private final LocalSocketImpl impl;
  private final LocalSocketAddress localAddress;
 
  private static final int LISTEN_BACKLOG = 50;
 
  /**
   * Create a LocalServerSocket from a file descriptor that's already
   * been created and bound. listen() will be called immediately on it.
   * Used for cases where file descriptors are passed in via environment
   * variables.
   */
  public LocalServerSocket(FileDescriptor fd) throws IOException {
    impl = new LocalSocketImpl(fd);
    impl.listen(LISTEN_BACKLOG);
    localAddress = impl.getSockAddress();
  }
}


registerZygoteSocket很简单,就是创建一个服务端的socket。
预加载类和资源——preload

我们先来看一下preload函数实现:

?
1
2
3
4
5
6
static void preload()
{
  preloadClasses();
  preloadResources();
  preloadOpenGL();
}

preload函数里面分别调用了三个预加载函数,我们分别来分析一下这几个函数的实现。

首先是preloadClasses,函数实现如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
private static final int UNPRIVILEGED_UID = 9999;
private static final int UNPRIVILEGED_GID = 9999;
 
private static final int ROOT_UID = 0;
private static final int ROOT_GID = 0;
 
private static void preloadClasses()
{
  final VMRuntime runtime = VMRuntime.getRuntime();
 
  InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(PRELOADED_CLASSES);
  if (is == null) {
    Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
  } else {
    Log.i(TAG, "Preloading classes...");
    long startTime = SystemClock.uptimeMillis();
 
    setEffectiveGroup(UNPRIVILEGED_GID);
    setEffectiveGroup(UNPRIVILEGED_UID);
 
    float defaultUtilization = runtime.getTargetHeapUtilization();
    runtime.setTargetHeapUtilization(0.8f);
 
    System.gc();
    runtime.runFinalizationSync();
    Debug.startAllocCounting();
 
    try {
      // 创建一个缓冲区为256字符的输入流
      BufferedReader br = new BufferdReader(new InputStreamReader(is), 256);
      int count = 0;
      String line;
      while ((line = br.readLine()) != null) {
        // skip comments and blank lines.
        line = line.trim();
        if (line.startsWith("#") || line.equals("")) {
          continue;
        }
 
        try {
          if (false) {
            Log.v(TAG, "Preloading " + line + "...");
          }
          Class.forName(line);
          count ++;
        } catch (ClassNotFoundException e) {
          Log.w(TAG, "Class not found for preloading: " + line);
        } catch (UnsatisfiedLinkError e) {
          Log.w(TAG, "Problem preloading " + line + ": " + e);
        } catch(Throwable t) {
          Log.e(TAG, "Error preloading " + line + ".", t);
        }
      }
      Log.i(TAG, "...preloaded " + count + " classes in " + (SystemClock.uptimeMillis()-startTime) + "ms.");
    } catch (IOException e) {
      Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
    } finally {
      IoUtils.closeQuietly(is);
      runtime.setTargetHeapUtilization(defaultUtilization);
 
      runtime.preloadDexCaches();
      Debug.stopAllocCounting();
 
      setEffectiveUser(ROOT_UID);
      setEffectiveGroup(ROOT_GID);
    }
  }
}


preloadClasses看起来很简单,但是实际上它有很多的类需要加载。可以查看一下/frameworks/base/preloaded-classes文件,这里面都是需要预加载的类。

接下来,分析一下preloadResources函数的源码:

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


接下来,是预加载OpenGL。源码如下:

?
1
2
3
4
5
6
private static void preloadOpenGL()
{
  if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
    EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
  }
}

启动system_server

现在我们要分析第三个关键点:startSystemServer。这个函数会创建java世界中系统Service所驻留的进程system_server,该进程是framework的核心。如何system_server挂掉,会导致zygote自杀。我们来看一下startSystemServer()实现源码。

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

 

有求必应之等待请求——runSelectLoop

zygote从startSystemServer返回后,将进入第四个关键的函数:runSelectLoop。我们来看一下这个函数的实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
static final int GC_LOOP_COUNT = 10;
private static void runSelectLoop() throws MethodAndArgsCaller {
  ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
  ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
  FileDescriptor[] fdArray = new FileDescriptor[4];
 
  fds.add(sServerSocket.getFileDescriptor());
  peers.add(null);
 
  int loopCount = GC_LOOP_COUNT;
  while (true) {
    int index;
    if (loopCount <= 0) {
      gc();
      loopCount = GC_LOOP_COUNT;
    } else {
      loopCount --;
    }
 
    try {
      fdArray = fds.toArray(fdArray);
      index = selectReadable(fdArray);
    } catch(IOException ex) {
      throw new RuntimeException("Error in select()", ex);
    }
 
    if (index < 0) {
      throw new RuntimeException("Error in select()");
    } else if (index == 0) {
      ZygoteConnection newPeer = acceptCommandPeer();
      peers.add(newPeer);
    }
  }
}

 

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
Intellij idea2020永久破解,亲测可用!!!
Intellij idea2020永久破解,亲测可用!!! 2020-07-29
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
返回顶部