首页 > 编程 > C > 正文

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

2020-01-26 15:00:45
字体:
来源:转载
供稿:网友

概述

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

zygote进程的启动脚本如下:

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):

/** * 将-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):

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:

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中确定的,其源码如下:

#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函数的源码实现:

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):

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数组,我们来看一下这个数组的实现:

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:

#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,源码如下:

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,实现代码如下:

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函数实现:

static void preload(){  preloadClasses();  preloadResources();  preloadOpenGL();}

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

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

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函数的源码:

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。源码如下:

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()实现源码。

/** * 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。我们来看一下这个函数的实现:

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);    }  }}

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选